BZOJ1095 [ZJOI2007]Hide 捉迷藏

时间:2022-02-07 09:29:13

  动态树分治,用三个set分别维护每个重心到每一个子树的距离种类、每个重心所有子树的最大值和次大值、全局答案的最大值。复杂度O(nlogn^2)

  代码

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<set>
  5 #define pb push_back
  6 using namespace std;
  7 const int N = 501010;
  8 int size[N],flag[N],n,a,b,i,f[N],cnt,typ[N],deep[N];
  9 int jump[N][18];
 10 int q;
 11 char ch[5];
 12 vector<int> e[N];
 13 multiset<int> dist[N],ans[N],Ans;
 14 multiset<int>::iterator it;
 15 int getroot(int x,int fa,int n)
 16 {
 17     int i,tmp=0,rt=0;
 18     size[x]=1;
 19     for (i=0;i<e[x].size();i++)
 20     if ((e[x][i]!=fa)&&(!flag[e[x][i]]))
 21     {
 22         rt|=getroot(e[x][i],x,n);
 23         size[x]+=size[e[x][i]];
 24         if (size[e[x][i]]>n/2) tmp=1;
 25     }
 26     if (n-size[x]>n/2) tmp=1;
 27     if (tmp==1) return rt;else return x;
 28 }
 29 void gao(int x,int fa,int y,int dis)
 30 {
 31     dis++;
 32     int i;
 33     dist[y].insert(dis);
 34     for (i=0;i<e[x].size();i++)
 35     if ((!flag[e[x][i]])&&(e[x][i]!=fa))
 36     gao(e[x][i],x,y,dis);
 37 }
 38 void DFS(int x,int fa)
 39 {
 40     int i;
 41     deep[x]=deep[fa]+1;
 42     jump[x][0]=fa;
 43     for (i=1;i<=17;i++)
 44     jump[x][i]=jump[jump[x][i-1]][i-1];
 45     for (i=0;i<e[x].size();i++)
 46     if (e[x][i]!=fa) DFS(e[x][i],x);
 47 }
 48 int lca(int a,int b)
 49 {
 50     int i;
 51     if (deep[a]<deep[b]) a^=b^=a^=b;
 52     for (i=17;i>=0;i--)
 53     if (deep[jump[a][i]]>=deep[b]) a=jump[a][i];
 54     if (a==b) return a;
 55     for (i=17;i>=0;i--)
 56     if (jump[a][i]!=jump[b][i]) a=jump[a][i],b=jump[b][i];
 57     return jump[a][0];
 58 }
 59 int getdis(int x,int y)
 60 {
 61     int z=lca(x,y);
 62     return deep[x]+deep[y]-2*deep[z];
 63 }
 64 void del(int x)
 65 {
 66     int tmp=0;
 67     if (ans[x].size()>=2)
 68     {
 69         it=ans[x].end();
 70         --it;tmp+=*it;
 71         --it;tmp+=*it;
 72         it=Ans.lower_bound(tmp);
 73         Ans.erase(it); 
 74     }
 75 }
 76 void ins(int x)
 77 {
 78     int tmp=0;
 79     if (ans[x].size()>=2)
 80     {
 81         it=ans[x].end();
 82         --it;tmp+=*it;
 83         --it;tmp+=*it;
 84         Ans.insert(tmp); 
 85     }
 86 }
 87 void DEL(int y)
 88 {
 89     if (dist[y].size())
 90     {
 91         it=dist[y].end();--it;
 92         int tmp=*it;
 93         it=ans[f[y]].lower_bound(tmp);
 94         ans[f[y]].erase(it);
 95     }
 96 } 
 97 void INS(int y)
 98 {
 99     if (dist[y].size())
100     {
101         it=dist[y].end();--it;
102         int tmp=*it;
103         ans[f[y]].insert(tmp);
104     }
105 }
106 int change(int x,int y)
107 {
108     del(x);
109     if (typ[x]==1) 
110     {
111         it=ans[x].lower_bound(0);
112         ans[x].erase(it);
113     } 
114     else
115         ans[x].insert(0);
116     while (x)
117     {
118         ins(x);
119         if (f[x]) 
120         { 
121             del(f[x]);
122             DEL(x);
123             int dis=getdis(f[x],y);
124             if (typ[y]==1)
125             {
126                 it=dist[x].lower_bound(dis);
127                 dist[x].erase(it);
128             }
129             else
130                 dist[x].insert(dis);
131             INS(x);
132         } 
133         x=f[x];
134     }
135 }
136 int dfs(int x,int n,int fa)
137 {
138     int i,y;
139     x=getroot(x,0,n);
140     f[x]=fa;
141     flag[x]=1;
142     ans[x].insert(0); 
143     for (i=0;i<e[x].size();i++)
144     if (!flag[e[x][i]])
145     {
146         if (size[e[x][i]]>size[x])
147             y=dfs(e[x][i],n-size[x],x);
148         else
149             y=dfs(e[x][i],size[e[x][i]],x);
150         gao(e[x][i],0,y,0);
151         it=dist[y].end();
152         ans[x].insert(*(--it));
153     }
154     ins(x);
155     flag[x]=0;
156     return x;
157 }
158 int main()
159 {
160     scanf("%d",&n);
161     for (i=1;i<n;i++)
162     {
163         scanf("%d%d",&a,&b);
164         e[a].pb(b);
165         e[b].pb(a);
166     }
167     dfs(1,n,0);
168     DFS(1,0);
169     scanf("%d",&q);
170     for (i=1;i<=q;i++)
171     {
172         scanf("%s",ch+1);
173         if (ch[1]=='G')
174         {
175             if (cnt==n)
176             printf("-1\n");
177             else
178             if (cnt==n-1)
179             printf("0\n");
180             else
181             {
182                 it=Ans.end();--it;
183                 printf("%d\n",*it);
184             }
185         }
186         else
187         if (ch[1]=='C')
188         {
189             scanf("%d",&a);
190             if (typ[a]==0) 
191             cnt++,typ[a]=1;
192             else 
193             cnt--,typ[a]=0;
194             change(a,a);
195         }
196     }
197 }