序列终结者
链接:https://www.luogu.org/problemnew/show/P4146
题解:
平衡树的区间修改操作,注意updata的时候要把左右儿子给down了
另外这题有负数
#include <bits/stdc++.h> #define maxn 111111 int num,n,m,fa[maxn],data[maxn],maxnumber[maxn],leftson[maxn], rightson[maxn],lazy[maxn],rev[maxn],count2[maxn],root; using namespace std; void down(int x) { if (lazy[x]) { maxnumber[x]+=lazy[x]; data[x]+=lazy[x]; if (leftson[x]) lazy[leftson[x]]+=lazy[x]; if (rightson[x]) lazy[rightson[x]]+=lazy[x]; lazy[x]=0; } if (rev[x]) { swap(rightson[x],leftson[x]); if (leftson[x]) rev[leftson[x]]^=1; if (rightson[x]) rev[rightson[x]]^=1; rev[x]=0; } } void updata(int x) { down(leftson[x]);down(rightson[x]); count2[x]=count2[leftson[x]]+count2[rightson[x]]+1; maxnumber[x]=max(data[x],max(maxnumber[leftson[x]],maxnumber[rightson[x]])); } void rotate(int x,int y) { int father=fa[x]; down(father); down(x); if (y==1) { rightson[father]=leftson[x]; if (leftson[x]) fa[leftson[x]]=father; } else { leftson[father]=rightson[x]; if (rightson[x]) fa[rightson[x]]=father; } fa[x]=fa[father]; if (fa[father]) { if (leftson[fa[father]]==father) leftson[fa[father]]=x; else rightson[fa[father]]=x; } fa[father]=x; if (y==1) leftson[x]=father; else rightson[x]=father; updata(father); updata(x); } void splay(int x,int goal) { if (x==root) return; int father; while (fa[x]!=goal) { father=fa[x]; if (fa[father]==goal) { if (x==leftson[father]) rotate(x,2); else rotate(x,1); } else { if (father==leftson[fa[father]]) { if (x==leftson[father]) rotate(father,2),rotate(x,2); else rotate(x,1),rotate(x,2); } else { if (x==rightson[father]) rotate(father,1),rotate(x,1); else rotate(x,2),rotate(x,1); } } } if (goal==0) root=x; } int search(int goal) { int x=root,cnt=1; while (x) { down(x); if (cnt+count2[leftson[x]]==goal) return(x); if (count2[leftson[x]]+cnt<goal) { cnt+=count2[leftson[x]]+1; x=rightson[x]; } else { x=leftson[x]; } } } void insert(int x) { int y=root; while (y) { count2[y]++; if (x<data[y]) { if (!leftson[y]) break; y=leftson[y]; } else { if (!rightson[y]) break; y=rightson[y]; } } data[++num]=0; fa[num]=y; count2[num]=1; if (x>data[y]) rightson[y]=num; else leftson[y]=num; splay(num,0); } void reserve(int x,int y) { int x1=search(x),y1=search(y+2); splay(x1,0); splay(y1,x1); rev[leftson[y1]]^=1; } void add(int x,int y,int sum) { int x1=search(x), y1=search(y+2); splay(x1,0); splay(y1,x1); lazy[leftson[y1]]+=sum; } void query(int x,int y) { int x1=search(x),y1=search(y+2); splay(x1,0); splay(y1,x1); down(leftson[y1]); cout<<maxnumber[leftson[y1]]<<endl; } int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); for (int i=0;i<=maxn-1;i++) maxnumber[i]=-2000000000; cin>>n>>m; for (int i=0;i<=n+1;i++) insert(rand()); for (int i=1;i<=m;i++) { // for (int i=1;i<=n+2;i++) cout<<leftson[i]<<" "<<rightson[i]<<endl; int c,d,e,f; cin>>c; if (c==1) { cin>>d>>e>>f; add(d,e,f); } if (c==2) { cin>>d>>e; reserve(d,e); } if (c==3) { cin>>d>>e; query(d,e); } } return 0; }