P15099 题解
场上先被 T1 卡两个多小时,拼尽全力写+调出 8k 代码翻盘,结果你跟我说降紫了???
首先需要注意到一个关键性质,一个 s 被至少一条 b 路径覆盖,当且仅当去掉这个点之后的连通块中,至少有两个连通块中存在 b 点。
对于一个 s 点 b 点 b 的时间)这段区间就不可能是一个合法区间的右端点(不然
先说怎么求出
但是覆盖了 b,且这个点和
注意以上都没有考虑一个点同时被标为 s 和 b 的情况,需要特判!
时间复杂度
// #pragma GCC optimize(2, 3, "Ofast")
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define MAXK 17
#define INF 1000000000
typedef pair<int, int> pii;
bool St;
int n, q, ct; int rt[MAXN], fa[MAXK][MAXN], dfn[MAXN], siz[MAXN], dep[MAXN], M[MAXN], ans[MAXN], rs[MAXN], bk[MAXN], pr[MAXN]; pair<int, int> qyy[MAXN];
vector<int> e[MAXN], va[MAXN], vb[MAXN]; struct Que{char c; int x;}que[MAXN]; vector<pair<int, int>> mod[MAXN];
pii meg(pii a, pii b){return {min(a.first, b.first), min(max(a.first, b.first), min(a.second, b.second))};}
pii meg(pii a, int b){return {min(a.first, b), min(max(a.first, b), a.second)};}
void dfs(int x, int f){dep[x] = dep[fa[0][x]=f]+1; dfn[x] = ++ct; siz[x] = 1; for (auto v: e[x]) if (v ^ f) dfs(v, x), siz[x] += siz[v];}
int kth(int x, int k){for (int i(0); i<MAXK; ++i) if (k>>i&1) x = fa[i][x]; return x;}
namespace Seg{
int tr[MAXN<<2];
void init(){fill(tr, tr+(MAXN<<2), INF);}
void mod(int p, int l, int r, int x, int k){
if (l == r){tr[p] = k; return;} int mid((l+r)>>1);
if (x <= mid) mod(p<<1, l, mid, x, k); else mod(p<<1|1, mid+1, r, x, k); tr[p] = min(tr[p<<1], tr[p<<1|1]);
}
int qry(int p, int l, int r, int L, int R){
if (L > R) return INF; if (L <= l && r <= R) return tr[p]; int mid((l+r)>>1), res(INF);
if (L <= mid) res = min(res, qry(p<<1, l, mid, L, R)); if (R > mid) res = min(res, qry(p<<1|1, mid+1, r, L, R)); return res;
}
}
namespace Seg2{
pii tr[MAXN<<2]; int tag[MAXN<<2];
pii meg(pii a, pii b){return a.first == b.first ? max(a, b) : min(a, b);}
void addtg(int p, int v){tr[p].first += v; tag[p] += v;}
void push_down(int p){for (; tag[p]; tag[p]=0) addtg(p<<1, tag[p]), addtg(p<<1|1, tag[p]);}
void bld(int p, int l, int r){if (l == r){tr[p] = {0, l}; return;} int mid((l+r)>>1); bld(p<<1, l, mid); bld(p<<1|1, mid+1, r); tr[p] = meg(tr[p<<1], tr[p<<1|1]);}
void mod(int p, int l, int r, int L, int R, int k){
// if (p == 1) cerr << "mod:" << L << ' ' << R << ' ' << k << '\n';
if (L <= l && r <= R){addtg(p, k); return;} int mid((l+r)>>1); push_down(p);
if (L <= mid) mod(p<<1, l, mid, L, R, k); if (R > mid) mod(p<<1|1, mid+1, r, L, R, k); tr[p] = meg(tr[p<<1], tr[p<<1|1]);
}
pii qry(int p, int l, int r, int L, int R){
if (L <= l && r <= R) return tr[p]; int mid((l+r)>>1); pii res(INF, 0);
if (L <= mid) res = meg(res, qry(p<<1, l, mid, L, R)); if (R > mid) res = meg(res, qry(p<<1|1, mid+1, r, L, R)); return res;
}
}
int kind(int u, int v){if (dep[v] <= dep[u] || kth(v, dep[v]-dep[u]) != u) return -1; return kth(v, dep[v]-dep[u]-1);}
bool Ed;
signed main(){
// freopen("excite.in", "r", stdin); freopen("excite.out", "w", stdout);
// cerr << (&Ed-&St)/1024.0/1024.0 << '\n';
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n; for (int i(1), u, v; i<n; ++i) cin >> u >> v, e[u].push_back(v), e[v].push_back(u); dfs(1, 0); cin >> q;
for (int j(1); j<MAXK; ++j) for (int i(1); i<=n; ++i) fa[j][i] = fa[j-1][fa[j-1][i]];
// cerr << kind(3, 5) << ' ' << dep[3] << ' ' << dep[5] << '\n';
// for (int i(1); i<=n; ++i) cerr << dfn[i] << ' '; cerr << '\n';
for (int i(1); i<=q; ++i){
cin >> que[i].c >> que[i].x;
if (que[i].c == 's') va[que[i].x].push_back(i);
else vb[que[i].x].push_back(i);
// cerr << que[i].c << ' ' << que[i].x << '\n';
// (que[i].c == 's' ? va : vb)[que[i].x].push_back(i);
}
// cerr << kind(1, 3) << '\n';
Seg::init();
for (int i(1); i<=q; ++i){
if (que[i].c == 's') Seg::mod(1, 1, n, dfn[que[i].x], n-i+1), rs[que[i].x] = i;
else{
int u(que[i].x), p(min(Seg::qry(1, 1, n, 1, dfn[u]-1), Seg::qry(1, 1, n, dfn[u]+1, n))); bk[i] = rs[que[i].x];
// cerr << p << '\n';
if (p ^ INF){
p = n-p+1; int v(que[p].x), yyx(kind(u, v)); vector<pair<int, int>> qry;
if (yyx == -1) qry.push_back({dfn[u]+1, dfn[u]+siz[u]-1});
else{
qry.push_back({1, dfn[u]-1}); qry.push_back({dfn[u]+1, dfn[yyx]-1}); qry.push_back({dfn[yyx]+siz[yyx], n});
}
int mnn(INF); for (auto [l, r]: qry) mnn = min(mnn, Seg::qry(1, 1, n, l, r)); qyy[i] = {p, mnn == INF ? INF : n-mnn+1};
// if (i == 2) cerr << mnn << ' ' << bk[i] << ' ' << yyx << ' ' << v << ' ' << p << '\n';
if (bk[i]){
if (bk[i] >= qyy[i].first) qyy[i] = {INF, INF};
else if (bk[i] >= qyy[i].second || qyy[i].second == INF) qyy[i].second = bk[i];
}
}else qyy[i] = {INF, INF};
}
}
// cerr << bk[1] << '\n';
// cerr << "YYX\n";
Seg::init(); Seg2::bld(1, 1, q); fill(pr+1, pr+n+1, q+1);
for (int i(q); i; --i){
// cerr << i << '\n';
for (auto [l, r]: mod[i]) if (l <= r) Seg2::mod(1, 1, q, l, r, -1);
if (que[i].c == 's') Seg::mod(1, 1, n, dfn[que[i].x], i), pr[que[i].x] = i;
else{
int u(que[i].x), p(min(Seg::qry(1, 1, n, 1, dfn[u]-1), Seg::qry(1, 1, n, dfn[u]+1, n)));
// cerr << "YYX\n" << p << '\n';
if (p ^ INF){
int v(que[p].x), yyx(kind(u, v)); vector<pair<int, int>> qry;
if (yyx == -1) qry.push_back({dfn[u]+1, dfn[u]+siz[u]-1});
else{
qry.push_back({1, dfn[u]-1}); qry.push_back({dfn[u]+1, dfn[yyx]-1}); qry.push_back({dfn[yyx]+siz[yyx], n});
}
int mnn(INF); for (auto [l, r]: qry) mnn = min(mnn, Seg::qry(1, 1, n, l, r));
if (mnn ^ INF){
Seg2::mod(1, 1, q, i, min(mnn, pr[u])-1, 1); int g(kind(u, que[p].x));
if (qyy[i].first ^ INF){
int v(qyy[i].first); bool fl(kind(u, que[v].x) != g); if (fl) mod[v].push_back({p, min(mnn, pr[u])-1});
if (qyy[i].second ^ INF){
if (fl) mod[qyy[i].second].push_back({i, min(p, pr[u])-1}); else mod[qyy[i].second].push_back({i, min(mnn, pr[u])-1});
}
}else if (bk[i]) mod[bk[i]].push_back({i, min(mnn, pr[u])-1});
}else{
// cerr << i << ' ' << qyy[i].first << ' ' << pr[u] << '\n';
Seg2::mod(1, 1, q, i, pr[u]-1, 1); int g(kind(u, que[p].x));
if (qyy[i].first ^ INF){
bool fl(kind(u, que[qyy[i].first].x) != g); if (fl) mod[qyy[i].first].push_back({p, pr[u]-1});
// cerr << fl << ' ' << (kind(u, que[qyy[i].first].x) != g) << ' ' << kind(u, que[qyy[i].first].x) << '\n';
if (qyy[i].second ^ INF){
if (fl) mod[qyy[i].second].push_back({i, min(p, pr[u])-1}); else mod[qyy[i].second].push_back({i, pr[u]-1});
}
}else if (bk[i]) mod[bk[i]].push_back({i, pr[u]-1});
}
}else{
// cerr << "YYX\n" ;
// cerr << "g:" << i << '\n';
Seg2::mod(1, 1, q, i, pr[u]-1, 1);
// if (i == 2) cerr << qyy[i].first << ' ' << qyy[i].second << '\n';
// cerr << bk[1] << ' ' << i << ' ' << pr[u]-1 << ' ' << (qyy[i].first == INF) << ' ' << bk[i] << '\n';
if (qyy[i].first == INF && bk[i]) mod[bk[i]].push_back({i, pr[u]-1});
if (qyy[i].second ^ INF) mod[qyy[i].second].push_back({i, pr[u]-1});
}
}
auto res(Seg2::qry(1, 1, q, i, q)); ans[i] = res.first ? 0 : res.second-i+1;
// cerr << res.first << ' ' << res.second << '\n';
}
for (int i(1); i<=q; ++i) cout << ans[i] << '\n';
return 0;
}