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;
}
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!

浙公网安备 33010602011771号