BZOJ4285: 使者
搞出dfs序,转化为查询矩形点数,树套树搞定。
#include<cstdio> #include<cstdlib> #define N 100005 #define IF else if struct edge{ edge*s; int v; } z[N*2],*next=z,*h[N]; int n,m,q; void add(int u,int v){ h[u]=&(*next++=(edge){ h[u],v } ); h[v]=&(*next++=(edge){ h[v],u } ); } typedef int ds[N]; ds d,p,r,l,son,y; void dfs1(int u){ r[u]=1; d[u]=d[p[u]]+1; int s=0; for(edge*i=h[u];i;i=i->s) if(i->v!=p[u]){ p[i->v]=u; dfs1(i->v); r[u]+=r[i->v]; if(s<r[i->v]) s=r[son[u]=i->v]; } } void dfs2(int u){ static int j; l[u]=++j; if(r[u]!=1){ y[son[u]]=y[u]; dfs2(son[u]); } for(edge*i=h[u];i;i=i->s) if(i->v!=p[u]&&i->v!=son[u]) dfs2(y[i->v]=i->v); } int lca(int s,int t){ while(y[s]^y[t]) d[y[s]]<d[y[t]]?(s^=t,t^=s,s^=t):0,s=p[y[s]]; return d[s]<d[t]?s:t; } struct node{ int v,s,a,q; node*l,*r; void up(){ s=l->s+r->s+a; } } *f[N],e[N*40]; node*back=e+1; node*create(int v){ return&(*back++=(node){ v,1,1,rand(),e,e } ); } void lturn(node*&s){ node*a=s->r; s->r=a->l; s->up(),a->l=s; a->up(),s=a; } void rturn(node*&s){ node*a=s->l; s->l=a->r; s->up(),a->r=s; a->up(),s=a; } void ins(int v,node*&s){ if(!s->s) s=create(v); IF(v==s->v)++s->a,s->up(); IF(v<s->v){ ins(v,s->l); if(s->l->q>s->q) rturn(s); else s->up(); } else{ ins(v,s->r); if(s->r->q>s->q) lturn(s); else s->up(); } } void del(int v,node*&s){ if(v<s->v) del(v,s->l),s->up(); IF(s->v<v)del(v,s->r),s->up(); IF(s->a>1)--s->a,s->up(); IF(s->l==e)s=s->r; IF(s->r==e)s=s->l; IF(s->l->q>s->r->q)rturn(s),del(v,s->r),s->up(); else lturn(s),del(v,s->l),s->up(); } int query(int v,node*s){ int k=0; for(;;s=s->r){ while(s->s&&v<s->v) s=s->l; if(!s->s) break; k+=s->l->s+s->a; } return k; } int query(int i,int j){ for(int k=0;;i^=i&-i){ if(!i) return k; k+=query(j,f[i]); } } void ins1(int i,int j){ for(;i<=n;i+=i&-i) ins(j,f[i]); } void ins2(int s,int t){ if(l[s]<l[t]) s^=t,t^=s,s^=t; ins1(l[t],l[s]); } void del1(int i,int j){ for(;i<=n;i+=i&-i) del(j,f[i]); } void del2(int s,int t){ if(l[s]<l[t]) s^=t,t^=s,s^=t; del1(l[t],l[s]); } int query(int i,int j,int s,int t){ return query(j,t)-query(j,s-1)-query(i-1,t)+query(i-1,s-1); } int find(int s,int t){ static int j; for(;y[s]^y[t];s=p[j]) j=y[s]; return s^t?son[t]:j; } int qtree(int s,int t){ if(d[s]<d[t]) s^=t,t^=s,s^=t; static int i,j,k; i=l[s],j=l[s]+r[s]-1; if(lca(s,t)!=t) return l[s]<l[t]?query(i,j,l[t],l[t]+r[t]-1):query(l[t],l[t]+r[t]-1,i,j); k=find(s,t); return(l[k]+r[k]>n?0:query(i,j,l[k]+r[k],n))+query(1,l[k]-1,i,j); } int main(){ struct{ operator int(){ int x; scanf("%d",&x); return x; } } it; n=it; for(int i=0;i<=n;++i) f[i]=e; for(int i=1;i!=n;++i) add(it,it); dfs1(1),dfs2(y[1]=1); for(m=it;m;--m) ins2(it,it); for(q=it;q;--q){ int k=it,s=it,t=it; if(k==3) printf("%d\n",qtree(s,t)); if(k==1) ins2(s,t); if(k==2) del2(s,t); } }