BZOJ 1095 [ZJOI2007]Hide 捉迷藏

题解:动态点分治

建立点分树,每个节点维护两个容器

记录本子树内到点分树父亲节点的路径长度集合

和自己所有子树内节点到自己的最长路径构成的集合

//语文不好,凑合着看吧QWQ

支持删除,所以用双堆来维护即可

同时维护全局堆统计答案

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=100009;
const int inf=1000000000;

int T;
int n,m;
int cntb;
int c[maxn];

int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	head[x]=cntedge;
}

int f[maxn][20];
int dep[maxn];
void Dfs(int now,int fa){
	f[now][0]=fa;
	dep[now]=dep[fa]+1;
	for(int i=head[now];i;i=nex[i]){
		if(to[i]==fa)continue;
		Dfs(to[i],now);
	}
}

void LCAinit(){
	for(int j=1;j<=19;++j){
		for(int i=1;i<=n;++i){
			f[i][j]=f[f[i][j-1]][j-1];
		}
	}
}

int Getlca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	for(int j=19;j>=0;--j){
		if(dep[f[u][j]]>=dep[v])u=f[u][j];
	}
	if(u==v)return u;
	for(int j=19;j>=0;--j){
		if(f[u][j]!=f[v][j]){
			u=f[u][j];v=f[v][j];
		}
	}
	return f[u][0];
}

inline int Getdist(int u,int v){
	int lca=Getlca(u,v);
	return dep[u]+dep[v]-2*dep[lca];
}


int nowsiz,root;
int vis[maxn];
int g[maxn];
int siz[maxn];
int divfa[maxn];
void Getroot(int x,int fa){
	siz[x]=1;g[x]=0;
	for(int i=head[x];i;i=nex[i]){
		if(to[i]==fa)continue;
		if(vis[to[i]])continue;
		Getroot(to[i],x);
		siz[x]+=siz[to[i]];
		g[x]=max(g[x],siz[to[i]]);
	}
	g[x]=max(g[x],nowsiz-siz[x]);
	if(g[x]<g[root])root=x;
}

int h[maxn];
priority_queue<int>q[maxn][4];
void Cle(int x,int y){
	while((!q[x][y].empty())&&(!q[x][y+1].empty())){
		if(q[x][y].top()==q[x][y+1].top()){
			q[x][y].pop();q[x][y+1].pop();
		}else{
			break;
		}
	}
}

void Geth(int x){
	Cle(x,0);
	if(c[x]){
		if(q[x][0].size()-q[x][1].size()<2){
			h[x]=0;
		}else{
			int tm=q[x][0].top();q[x][0].pop();
			Cle(x,0);
			h[x]=tm+q[x][0].top();q[x][0].push(tm);
		}
	}else{
		if(q[x][0].size()-q[x][1].size()==0){
			h[x]=0;
		}else if(q[x][0].size()-q[x][1].size()==1){
			h[x]=q[x][0].top();
		}else{
			int tm=q[x][0].top();q[x][0].pop();
			Cle(x,0);
			h[x]=tm+q[x][0].top();q[x][0].push(tm);
		}
	}
}

void Getsiz(int x,int fa){
	siz[x]=1;
	for(int i=head[x];i;i=nex[i]){
		if(vis[to[i]])continue;
		if(to[i]==fa)continue;
		Getsiz(to[i],x);
		siz[x]+=siz[to[i]];
	}
}

//0,1    2,3
void Getq2(int x,int fa,int dd,int rt){
	q[rt][2].push(dd);
	for(int i=head[x];i;i=nex[i]){
		if(to[i]==fa)continue;
		if(vis[to[i]])continue;
		Getq2(to[i],x,dd+1,rt);
	}
}

void Sol(int x){
	vis[x]=1;
	//维护q[2],q[3];
	Getsiz(x,0);
	for(int i=head[x];i;i=nex[i]){
		if(vis[to[i]])continue;
		nowsiz=siz[to[i]];root=0;
		Getroot(to[i],x);
		divfa[root]=x;
		Getq2(to[i],x,1,root);
		q[x][0].push(q[root][2].top());
	}
	Geth(x);
	q[0][0].push(h[x]);
	for(int i=head[x];i;i=nex[i]){
		if(vis[to[i]])continue;
		nowsiz=siz[to[i]];root=0;
		Getroot(to[i],x);
		Sol(root);
	}
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n-1;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		Addedge(x,y);
		Addedge(y,x);
	}
	Dfs(1,0);
	LCAinit();
	g[0]=inf;nowsiz=n;
	Getroot(1,0);
	Sol(root);
	
	cntb=n;
	scanf("%d",&T);
	while(T--){
		char opty=getchar();
		while(opty!='C'&&opty!='G')opty=getchar();
		int x;
		if(opty=='C'){
			scanf("%d",&x);
			if(c[x]==0){
				c[x]=1;--cntb;
				int y=x;
				while(y){
					q[0][1].push(h[y]);
					Geth(y);
					q[0][0].push(h[y]);
					if(divfa[y]){
						Cle(y,2);
						q[divfa[y]][1].push(q[y][2].top());
						int tm=Getdist(divfa[y],x);
						q[y][3].push(tm);
						Cle(y,2);
						if(q[y][2].size()-q[y][3].size()>0)q[divfa[y]][0].push(q[y][2].top());
					}
					y=divfa[y];
				}
			}else{
				c[x]=0;++cntb;
				int y=x;
				while(y){
					q[0][1].push(h[y]);
					Geth(y);
					q[0][0].push(h[y]);
					if(divfa[y]){
						Cle(y,2);
						if(q[y][2].size()-q[y][3].size()>0)q[divfa[y]][1].push(q[y][2].top());
						int tm=Getdist(divfa[y],x);
						q[y][2].push(tm);
						Cle(y,2);
						q[divfa[y]][0].push(q[y][2].top());
					}
					y=divfa[y];
				}
			}
		}else{
			if(cntb==0){
				printf("%d\n",-1);
			}else if(cntb==1){
				printf("%d\n",0);
			}else{
				Cle(0,0);
				printf("%d\n",q[0][0].top());
			}
		}
	}
	return 0;
}

  

posted @ 2018-02-19 20:45  ws_zzy  阅读(149)  评论(0编辑  收藏  举报