zoukankan      html  css  js  c++  java
  • 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
    ",-1);
    			}else if(cntb==1){
    				printf("%d
    ",0);
    			}else{
    				Cle(0,0);
    				printf("%d
    ",q[0][0].top());
    			}
    		}
    	}
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    【Oracle 12c】最新CUUG OCP-071考试题库(58题)
    【Oracle 12c】最新CUUG OCP-071考试题库(57题)
    【Oracle 12c】最新CUUG OCP-071考试题库(56题)
    【Oracle 12c】最新CUUG OCP-071考试题库(55题)
    voip,
    处理xmpp 离线信息,
    流程,xmpp发送信息,
    折腾我几天的 消息状态,
    三者的区别,
    bundle,
  • 原文地址:https://www.cnblogs.com/zzyer/p/8454388.html
Copyright © 2011-2022 走看看