Solution - P2056 [ZJOI2007] 捉迷藏

我实在是唐到了一个程度……对着一个 4.5k 的代码调了 15h 才调出来

思路

就是一个点分树。

众所周知,点分树需要维护两个数据结构来存对自身和对父亲的贡献,而在这道题里,这个数据结构是一只可删堆。

于是对于修改向上维护就行了。

代码

#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 100005
using namespace std;

int to[N<<1], nxt[N<<1], head[N], gsiz = 1;
#define mkarc(u,v) (++gsiz, to[gsiz]=v, nxt[gsiz]=head[u], head[u]=gsiz) 
int fa2[N], dep2[N], dis[N][20], vis[N];
int siz[N], col[N], cnt;
int n, q;

struct Heap{
	priority_queue<int> A, B;
	inline void insert(rint x){A.push(x); return;}
	inline void erase (rint x){B.push(x); return;}
	inline int  size(){return A.size()-B.size();}
	inline void pop(){
		while(!B.empty() && A.top() == B.top()) A.pop(), B.pop();
		if(!A.empty()) A.pop();
		return;
	}
	inline int top(){
		while(!B.empty() && A.top() == B.top()) A.pop(), B.pop();
		if(A.empty()) return 0;
		return A.top();
	}
	inline int sec(){
		rint tmp = top(); pop();
		rint res = top();
		insert(tmp);
		return res;
	}
} sub[N], all[N], ans;

namespace lca{
	int dep[N], fa[N][21];
	inline void init(rint u = 1, rint _fa = 0){
		for(rint i = 1; i < 20; ++i)
			fa[u][i] = fa[fa[u][i-1]][i-1];
		for(rint i = head[u]; i; i = nxt[i]){
			rint v = to[i];
			if(v == _fa) continue;
			dep[v] = dep[u]+1, fa[v][0] = u;
			init(v, u);
		}
		return;
	}
	inline int lca(rint u, rint v){
		if(dep[u] > dep[v]) swap(u, v);
		for(rint i = 20; i >= 0; --i)
			if(dep[fa[v][i]] >= dep[u]) v = fa[v][i];
		if(u == v) return u;
		for(rint i = 20; i >= 0; --i)
			if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
		return fa[u][0];
	}
	inline int dis(rint u, rint v){
		return dep[u]+dep[v]-2*dep[lca(u,v)];
	}
}

inline void dfs1(rint u, rint fa, rint sum, rint& minn, rint& g){
	rint mink = 0;
	siz[u] = 1;
	for(rint i = head[u]; i; i = nxt[i]){
		rint v = to[i];
		if(v == fa || vis[v]) continue;
		dfs1(v, u, sum, minn, g);
		siz[u] += siz[v], mink = max(mink, siz[v]);
	}
	mink = max(mink, sum-siz[u]);
	if(minn > mink) g = u, minn = mink;
	return;
}

inline int dfs2(rint u, rint fa, rint dep, Heap& h){
	rint maxn = dep; h.insert(dep);
	for(rint i = head[u]; i; i = nxt[i]){
		rint v = to[i];
		if(v == fa || vis[v]) continue;
		maxn = max(maxn, dfs2(v, u, dep+1, h));
	}
	return maxn;
}

inline void prework(rint u){
	vis[u] = true, sub[u].insert(0);
	for(rint i = head[u]; i; i = nxt[i]){
		rint v = to[i], sum = siz[v], minn = 1e9+7;
		if(vis[v]) continue;
		dfs1(v, 0, sum, minn, v);
		dfs1(v, 0, sum, minn, v);
		fa2[v] = u, dep2[v] = dep2[u]+1;
		sub[u].insert(dfs2(to[i], u, 1, all[v]));
		prework(v);
	}
	if(sub[u].size() >= 2) ans.insert(sub[u].top()+sub[u].sec());
	else                   ans.insert(sub[u].top());
	return;
}

#define getdis(u,v) (dis[u][dep2[u]-dep2[v]])

int main(){
	scanf("%d", &n);
	for(rint i = 1; i < n; ++i){
		rint u, v, w;
		scanf("%d %d", &u, &v);
		mkarc(u, v), mkarc(v, u);
	}
	siz[1] = cnt = n;
	lca::init(); 
	rint minn = 1e9+7, g;
	dfs1(1, 0, n, minn, g);
	dfs1(g, 0, n, minn, g);
	dep2[g] = 1;
	prework(g);
	for(rint i = 1; i <= n; ++i)
		for(rint j = i; j; j = fa2[j])
			dis[i][dep2[i]-dep2[j]] = lca::dis(i, j);
	scanf("%d", &q);
	while(q--){
		char op[2];
		scanf("%s", op);
		if(op[0] == 'G'){
			if(cnt == 0)
				puts("-1");
			else
				printf("%d\n", ans.top());
		}
		else{
			rint x = 0;
			scanf("%d", &x);
			if(col[x] == 0){
				if(sub[x].size() >= 2) ans.erase(sub[x].top()+sub[x].sec());
				sub[x].erase(0);
				if(sub[x].size() >= 2) ans.insert(sub[x].top()+sub[x].sec());
				for(rint i = x; fa2[i]; i = fa2[i]){
					if(sub[fa2[i]].size() >= 2) ans.erase(sub[fa2[i]].top()+sub[fa2[i]].sec());
					if(all[i].size()) sub[fa2[i]].erase(all[i].top());
					all[i].erase(getdis(x, fa2[i]));
					if(all[i].size()) sub[fa2[i]].insert(all[i].top());
					if(sub[fa2[i]].size() >= 2) ans.insert(sub[fa2[i]].top()+sub[fa2[i]].sec());
				}
				--cnt;
			}
			else{
				if(sub[x].size() >= 2) ans.erase(sub[x].top()+sub[x].sec());
				sub[x].insert(0);
				if(sub[x].size() >= 2) ans.insert(sub[x].top()+sub[x].sec());
				for(rint i = x; fa2[i]; i = fa2[i]){
					if(sub[fa2[i]].size() >= 2) ans.erase(sub[fa2[i]].top()+sub[fa2[i]].sec());
					if(all[i].size()) sub[fa2[i]].erase(all[i].top());
					all[i].insert(getdis(x, fa2[i]));
					if(all[i].size()) sub[fa2[i]].insert(all[i].top());
					if(sub[fa2[i]].size() >= 2) ans.insert(sub[fa2[i]].top()+sub[fa2[i]].sec());
				}
				++cnt;
			}
			col[x] ^= 1;
		}
	}
	return 0;
}
posted @ 2025-05-19 23:09  Hootime  阅读(7)  评论(0)    收藏  举报