[bzoj3159]决战
来自FallDream的博客,未经允许,请勿转载,谢谢。
n,m<=50000
考虑树链剖分,并对于每条重链维护一棵无旋treap
15操作的时候把treap Merge到一起,打完标记,然后拆回去
234操作直接查
复杂度nlog^2n
#include<iostream> #include<cstdio> #define ll long long #define MN 50000 #define INF 2000000000 #define Sz(x) (x?x->size:0) using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } inline int Ran() { static int r=23333; r^=(r<<13);r^=(r>>17);r^=(r<<5); return r; } struct Treap { Treap *l,*r; int size,k,mx,mn,x,val;ll sum;bool rev; Treap(){} Treap(int X){size=1;k=Ran();sum=mx=mn=x=X;rev=0;l=r=NULL;} void Add(int ad){sum+=1LL*size*ad;val+=ad;mn+=ad;mx+=ad;x+=ad;} void Rev(){swap(l,r);rev^=1;} void update() { size=Sz(l)+Sz(r)+1;mx=mn=sum=x; if(l) sum+=l->sum,mx=max(mx,l->mx),mn=min(mn,l->mn); if(r) sum+=r->sum,mx=max(mx,r->mx),mn=min(mn,r->mn); } void pushdown() { if(val) l?(l->Add(val),0):0,r?(r->Add(val),0):0,val=0; if(rev) l?(l->Rev(),0):0,r?(r->Rev(),0):0,rev=0; } }*rt[MN+5]; typedef pair<Treap*,Treap*> D; struct edge{int to,next;}e[MN*2+5]; int n,m,Rt,head[MN+5],cnt=0,top[MN+5],fa[MN+5],size[MN+5],mx[MN+5],dep[MN+5]; inline void ins(int f,int t) { e[++cnt]=(edge){t,head[f]};head[f]=cnt; e[++cnt]=(edge){f,head[t]};head[t]=cnt; } D Split(Treap*x,int rk) { if(!x) return D(NULL,NULL); x->pushdown();int sz=Sz(x->l);D b; if(sz>=rk) { b=Split(x->l,rk); x->l=b.second;x->update(); b.second=x; } else { b=Split(x->r,rk-sz-1); x->r=b.first;x->update(); b.first=x; } return b; } Treap* Merge(Treap*x,Treap*y) { if(!x) return y;if(!y) return x; if(x->k<y->k) { x->pushdown(); x->r=Merge(x->r,y); x->update();return x; } else { y->pushdown(); y->l=Merge(x,y->l); y->update();return y; } } void Pre(int x,int f) { fa[x]=f;size[x]=1;mx[x]=0; for(int i=head[x];i;i=e[i].next) if(e[i].to!=f) { dep[e[i].to]=dep[x]+1;Pre(e[i].to,x); size[x]+=size[e[i].to]; if(size[e[i].to]>size[mx[x]]) mx[x]=e[i].to; } } void Dfs(int x,int tp) { top[x]=tp;Treap*now=new Treap(0); rt[tp]=Merge(rt[tp],now); if(mx[x]) Dfs(mx[x],tp); for(int i=head[x];i;i=e[i].next) if(e[i].to!=fa[x]&&e[i].to!=mx[x]) Dfs(e[i].to,e[i].to); } char op[15]; int main() { n=read();m=read();dep[Rt=read()]=1; for(int i=1;i<=n;++i) rt[i]=NULL; for(int i=1;i<n;++i) ins(read(),read()); Pre(Rt,0);Dfs(Rt,Rt); for(int i=1;i<=m;++i) { scanf("%s",op+1);int x=read(),y=read(); if(op[1]=='I') { if(dep[x]<dep[y]) swap(x,y); Treap*s=NULL;D ss; for(int t=x;t;t=fa[top[t]]) { ss=Split(rt[top[t]],dep[t]-dep[top[t]]+1); s=Merge(ss.first,s);rt[top[t]]=ss.second; } D b=Split(s,dep[y]-1),c=Split(b.second,dep[x]-dep[y]+1); if(op[3]=='c') c.first->Add(read()); else c.first->Rev(); s=Merge(b.first,Merge(c.first,c.second)); for(int t=x;t;t=fa[top[t]]) { D b=Split(s,dep[top[t]]-1); rt[top[t]]=Merge(b.second,rt[top[t]]);s=b.first; } } else { ll res=(op[2]=='i')?INF:0; for(;top[x]!=top[y];x=fa[top[x]]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); D b=Split(rt[top[x]],dep[x]-dep[top[x]]+1); if(op[1]=='S') res+=b.first->sum; if(op[2]=='a') res=max(res,(ll)b.first->mx); if(op[2]=='i') res=min(res,(ll)b.first->mn); rt[top[x]]=Merge(b.first,b.second); } if(dep[x]>dep[y]) swap(x,y); D b=Split(rt[top[x]],dep[x]-dep[top[x]]); D c=Split(b.second,dep[y]-dep[x]+1); if(op[1]=='S') res+=c.first->sum; if(op[2]=='a') res=max(res,(ll)c.first->mx); if(op[2]=='i') res=min(res,(ll)c.first->mn); rt[top[x]]=Merge(b.first,Merge(c.first,c.second)); printf("%lld\n",res); } } return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream