BZOJ 1251 序列终结者
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1251
这题就是充分利用文艺平衡树那题留下的心理阴影啊...
总之,我们已经知道平衡树可以像线段树一样操作[非递归线段树的感觉...],不过平衡树支持神奇的翻转操作...[这个见文艺平衡树]
然后就是tag的下传和向上更新了...一定要注意细节啊~什么左子树右子树是不是为空,还是要仔细看一看的啦...
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; inline int in(){ int x=0,f=1;char ch=getchar(); while((ch>'9' || ch<'0') && ch!='-') ch=getchar(); if(ch=='-') f=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } const int maxn=100010; struct Node{ int Mx,sz,dt; int l,r,f; int ad; bool mk; void trans(){swap(l,r);} }s[maxn]; int rt,n,m; void update(int x){ s[x].sz=s[s[x].l].sz+s[s[x].r].sz+1; s[x].Mx=s[x].dt; if(s[x].l) s[x].Mx=max(s[x].Mx,s[s[x].l].Mx); if(s[x].r) s[x].Mx=max(s[x].Mx,s[s[x].r].Mx); } void push_down(int x){ if(s[x].mk){ s[x].trans();s[x].mk=0; if(s[x].l) s[s[x].l].mk^=1; if(s[x].r) s[s[x].r].mk^=1; } if(s[x].ad){ if(s[x].l) {s[s[x].l].ad+=s[x].ad;s[s[x].l].dt+=s[x].ad;s[s[x].l].Mx+=s[x].ad;} if(s[x].r) {s[s[x].r].ad+=s[x].ad;s[s[x].r].dt+=s[x].ad;s[s[x].r].Mx+=s[x].ad;} s[x].ad=0; } } int build(int l,int r){ if(l>r) return 0; int mid=(l+r)>>1; s[mid].l=build(l,mid-1); s[mid].r=build(mid+1,r); update(mid); if(s[mid].l) s[s[mid].l].f=mid; if(s[mid].r) s[s[mid].r].f=mid; return mid; } void zig(int x){ int y=s[x].f; s[x].f=s[y].f; if(s[y].f){ if(y==s[s[y].f].l) s[s[y].f].l=x; else s[s[y].f].r=x; } s[y].l=s[x].r; if(s[x].r) s[s[x].r].f=y; s[x].r=y;s[y].f=x; update(y),update(x); } void zag(int x){ int y=s[x].f; s[x].f=s[y].f; if(s[y].f){ if(y==s[s[y].f].l) s[s[y].f].l=x; else s[s[y].f].r=x; } s[y].r=s[x].l; if(s[x].l) s[s[x].l].f=y; s[x].l=y;s[y].f=x; update(y),update(x); } void Splay(int x,int gf){ int y; while(s[x].f!=gf){ y=s[x].f; if(s[y].f==gf){ if(x==s[y].l) zig(x); else zag(x); } else{ int z=s[y].f; if(y==s[z].l){ if(x==s[y].l) zig(y),zig(x); else zag(x),zig(x); } else{ if(x==s[y].r) zag(y),zag(x); else zig(x),zag(x); } } } if(!gf) rt=x; } int Find(int k){ int p=rt; while(p){ push_down(p); if(k<=s[s[p].l].sz) p=s[p].l; else{ k-=s[s[p].l].sz; if(k==1) return p; k--;p=s[p].r; } } } void add(int L,int R,int k){ int a=Find(L),b=Find(R+2); Splay(a,0);Splay(b,a); s[s[b].l].ad+=k,s[s[b].l].dt+=k,s[s[b].l].Mx+=k; } void rev(int L,int R){ int a=Find(L),b=Find(R+2); Splay(a,0);Splay(b,a); s[s[b].l].mk^=1; } int ask(int L,int R){ int a=Find(L),b=Find(R+2); Splay(a,0);Splay(b,a); return s[s[b].l].Mx; } int main(){ #ifndef ONLINE_JUDGE freopen("1512.in","r",stdin); freopen("1512.out","w",stdout); #endif int ord,L,R,k; n=in(),m=in(); rt=build(1,n+2); while(m--){ ord=in();L=in(),R=in(); if(ord==1) k=in(),add(L,R,k); else if(ord==2) rev(L,R); else printf("%d\n",ask(L,R)); } return 0; }