BZOJ1095 [ZJOI2007]Hide 捉迷藏
动态树分治,用三个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 }