【BZOJ1095】【ZJOI2007】捉迷藏 [动态点分治]
题解:
好像还是比较简单的
对每个重心向下一层重心连边
树高是log的
我们对每一层维护两个信息
1.所有节点到上一层重心的距离
2.所有儿子的1堆的堆顶
另外开个总的堆 维护每一层最长+次长
修改是nlog^2的
洛谷上的时限真紧啊。。
卡时卡不过
代码:
#include <bits/stdc++.h> using namespace std; const int N=2e5+100; const int INF=1e9; #define IL inline #define rint register int #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (ritn i=t;i>=h;i--) char ss[1<<24],*A=ss,*B=ss; IL char gc() { return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T>IL void read(T &x) { rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48); while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } IL void read2(char &x) { rint c; while (c=gc(),c!='G'&&c!='C'); x=c; } char sr[1<<24],z[20]; int C=-1,Z; template <class T> void wer(T x) { if (x<0) sr[++C]='-',x=-x; while (z[++Z]=x%10+48,x/=10); while (sr[++C]=z[Z],--Z); sr[++C]='\n'; } struct PQ{ struct cmp{ IL bool operator() (int x,int y) { return(x<y); } }; priority_queue<int>Q1,Q2; IL void push(int x) {Q1.push(x);} IL void erase(int x) {Q2.push(x);} IL int top() { while (Q2.size()&&Q2.top()==Q1.top()) Q1.pop(),Q2.pop(); if (Q1.size()) return(Q1.top()); else return(-INF); } IL void pop() { while (Q2.size()&&Q2.top()==Q1.top()) Q1.pop(),Q2.pop(); Q1.pop(); } IL int sec_top() { int tmp=top(); if (tmp>0) pop(); int x=top(); if (tmp>0) push(tmp); return x; } }Q1[N],Q2[N],QQ; int n,l,head[N],dep[N],bz[20][N],f[N],son[N],fa[N],rt,ans1[N],ans2[N]; int sum; bool vis[N]; struct re{ int a,b; }a[N*2]; void arr(int x,int y) { a[++l].a=head[x]; a[l].b=y; head[x]=l; } IL int lca(int x,int y) { if (dep[x]<dep[y]) swap(x,y); for (int i=19;i>=0;i--) if (dep[bz[i][x]]>=dep[y]) x=bz[i][x]; if (x==y) return(x); for (int i=19;i>=0;i--) if (bz[i][x]!=bz[i][y]) x=bz[i][x],y=bz[i][y]; return(bz[0][x]); } IL int js(int x,int y) { int kk=lca(x,y); return(dep[x]+dep[y]-2*dep[kk]); } void dfs(int x,int fa) { int u=head[x]; dep[x]=dep[fa]+1; bz[0][x]=fa; while (u) { int v=a[u].b; if (v!=fa) dfs(v,x); u=a[u].a; } } void fr(int x,int fa) { f[x]=0; son[x]=1; int u=head[x]; while (u) { int v=a[u].b; if (v!=fa&&vis[v]) { fr(v,x); f[x]=max(f[x],son[v]); son[x]+=son[v]; } u=a[u].a; } f[x]=max(f[x],sum-son[x]); if (f[x]<f[rt]) rt=x; } void fd(int x,int y,int kk,int z) { int jl=js(x,kk); Q1[z].push(jl); int u=head[x]; while (u) { int v=a[u].b; if (v!=y&&vis[v]) fd(v,x,kk,z); u=a[u].a; } } void solve(int x,int y,int z) { //cout<<z<<endl; int u=head[x]; fa[x]=y; vis[x]=0; if (x!=1) { fd(x,y,y,x),Q2[y].push(Q1[x].top()); ans1[x]=Q1[x].top(); } Q2[x].push(0); while (u) { int v=a[u].b; if (vis[v]) { rt=0; sum=son[v]; fr(v,x); solve(rt,x,z+1); } u=a[u].a; } } int cnt1,cnt2; IL int cl(int x,int y) { cnt1++; if (y>ans1[x]) { Q2[fa[x]].erase(ans1[x]); ans1[x]=y; Q2[fa[x]].push(ans1[x]); return(1); } return(0); } IL int cl3(int x,int y) { if (y==ans1[x]) { Q2[fa[x]].erase(ans1[x]); ans1[x]=Q1[x].top(); Q2[fa[x]].push(ans1[x]); return(1); } return(0); } IL void cl2(int x) { cnt2++; int num=Q2[x].top()+Q2[x].sec_top(); if (num!=ans2[x]) { if (ans2[x]>0) QQ.erase(ans2[x]); ans2[x]=num; if (ans2[x]>0) QQ.push(ans2[x]); } } IL void change(int x,int y) { if (y==1) Q2[x].push(0); else Q2[x].erase(0); cl2(x); rint z=x; while (z!=1) { rint jl=js(x,fa[z]); if (y==1) { Q1[z].push(jl); if (cl(z,jl)) cl2(fa[z]); } else { Q1[z].erase(jl); if (cl3(z,jl)) cl2(fa[z]); } z=fa[z]; } } bool t[N]; int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); // ios::sync_with_stdio(false); read(n); for (int i=1;i<=n-1;i++) { int x,y; read(x); read(y); arr(x,y); arr(y,x); } memset(vis,1,sizeof(vis)); dfs(1,0); rep(i,1,19) rep(j,1,n) bz[i][j]=bz[i-1][bz[i-1][j]]; f[0]=INF; solve(1,0,0); rep(i,1,n) { int num; num=ans2[i]=Q2[i].top()+Q2[i].sec_top(); if (num>0) QQ.push(num); } memset(t,1,sizeof(t)); int m; read(m); char kk; rep(i,1,m) { int x; read2(kk); if (kk=='G') { wer(QQ.top()); } else { read(x); if (t[x]==1) { t[x]=0; change(x,0); } else { t[x]=1; change(x,1); } } } // cout<<cnt1<<endl<<cnt2<<endl; fwrite(sr,1,C+1,stdout); return 0; }