发现动态树分治还是挺好玩的。。。。。。。然而效率有点拙计
跑了14S多,差点以为要TLE,回头一看发现时限40S。
模板抄的PoPoQQQ大爷的,顺便看了下漆神的论文,各种吓Cry。
准备水下QTREE4,听说SPOJ的机子很慢,好虚啊。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=100000+5; struct Heap{ priority_queue<int>heap,del; void Push(int x){ heap.push(x); } void Erase(int x){ del.push(x); } void Pop(){ while(del.size()&&del.top()==heap.top()) del.pop(),heap.pop(); heap.pop(); } int Top(){ while(del.size()&&del.top()==heap.top()) del.pop(),heap.pop(); return heap.top(); } int Second_Top(){ int tmp=Top();Pop(); int ret=Top();Push(tmp); return ret; } int Size(){ return heap.size()-del.size(); } }h1[N],h2[N],ans; struct Edge{int to,next;bool ban;}e[N<<1]; int head[N],cnt=1; void ins(int u,int v){ e[++cnt]=(Edge){v,head[u],false};head[u]=cnt; } int log2[N<<1],st[N<<1][20],sz,dep[N],pos[N]; bool mark[N]; int fa[N]; int getsize(int u,int fa){ int ret=1; for(int i=head[u];i;i=e[i].next){ if(e[i].to==fa||e[i].ban)continue; ret+=getsize(e[i].to,u); } return ret; } int findroot(int u,int fa,int size,int& root){ int ret=1;bool flag=true; for(int i=head[u];i;i=e[i].next){ if(e[i].ban||e[i].to==fa)continue; int tmp=findroot(e[i].to,u,size,root); if(tmp<<1>size)flag=false; ret+=tmp; } if(size-ret<<1>size)flag=false; if(flag)root=u; return ret; } void dfs(int u,int fa,int depth,Heap &s){ s.Push(depth); for(int i=head[u];i;i=e[i].next) if(!e[i].ban&&e[i].to!=fa)dfs(e[i].to,u,depth+1,s); } void Insert(Heap &s){ if(s.Size()>=2)ans.Push(s.Top()+s.Second_Top()); } void Erase(Heap &s){ if(s.Size()>=2)ans.Erase(s.Top()+s.Second_Top()); } int divide(int u){ int size=getsize(u,0),root; findroot(u,0,size,root); h2[root].Push(0); for(int i=head[root];i;i=e[i].next) if(!e[i].ban){ e[i].ban=e[i^1].ban=true; Heap s; dfs(e[i].to,0,1,s); int tmp=divide(e[i].to); fa[tmp]=root;h1[tmp]=s; h2[root].Push(h1[tmp].Top()); } Insert(h2[root]); return root; } void dfs(int u,int fa){ st[pos[u]=++sz][0]=dep[u]=dep[fa]+1; for(int i=head[u];i;i=e[i].next) if(e[i].to!=fa){ dfs(e[i].to,u); st[++sz][0]=dep[u]; } } void rmq_init(){ for(int j=1;1<<j <=sz;j++) for(int i=1;i+(1<<j)-1<=sz;i++) st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); } int rmq(int x,int y){ x=pos[x];y=pos[y]; if(x>y)swap(x,y); int k=log2[y-x+1]; return min(st[x][k],st[y-(1<<k)+1][k]); } int dis(int x,int y){ return dep[x]+dep[y]-2*rmq(x,y); } void change(int x,bool flag){ Erase(h2[x]); if(flag)h2[x].Erase(0); else h2[x].Push(0); Insert(h2[x]); for(int i=x;fa[i];i=fa[i]){ Erase(h2[fa[i]]); if(h1[i].Size())h2[fa[i]].Erase(h1[i].Top()); if(flag)h1[i].Erase(dis(fa[i],x)); else h1[i].Push(dis(fa[i],x)); if(h1[i].Size())h2[fa[i]].Push(h1[i].Top()); Insert(h2[fa[i]]); } } int tot; int main(){ int n;scanf("%d",&n); int u,v; for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); ins(u,v);ins(v,u); } divide(1); dfs(1,0); for(int i=2;i<=sz;i++)log2[i]=log2[i>>1]+1; rmq_init(); int q;scanf("%d",&q);char opt[5];int x; tot=n; while(q--){ scanf("%s",opt); if(opt[0]=='G'){ if(tot<=1)printf("%d\n",tot-1); else printf("%d\n",ans.Top()); }else{ scanf("%d",&x); if(mark[x])tot++; else tot--; change(x,mark[x]^=1); } } return 0; }