poj 3580 splay
题意:
1 区间每个数加D
2 区间翻转
3 区间向右滚动T次 12345滚动1次为51234
4 第x个数后面添加p
5 删除第x个数
6 询问区间最小值
分析:结点[0]的信息不能修改,原因不明。。。
翻转操作不能直接rev[x]=1, 而要rev[x]^=1。 keyTree未必已经pushDown
pushDown(x) if(x==0)return; 可以节省不少时间
#define keyTree (ch[ ch[root][1] ][0]) const int vaf=0x7fffffff; const int MaxN = 100005; struct SplayTree{ int sz[MaxN]; int ch[MaxN][2];//ch[][0]左孩子 ch[][1]右孩子 int pre[MaxN];//父结点 int root,top1,top2; int sta[MaxN],que[MaxN]; inline void Rotate(int x,int f) {//f==0左旋转 f==1右旋转 int y=pre[x]; PushDown(y); PushDown(x); ch[y][!f]=ch[x][f]; pre[ch[x][f]]=y; pre[x]=pre[y]; if(pre[x]) ch[pre[y]][ch[pre[y]][1]==y]=x; ch[x][f]=y; pre[y]=x; PushUp(y); //if(y==root)root=x; } inline void Splay(int x,int goal) {//将x旋转到goal的下面 PushDown(x); while(pre[x]!=goal) { if(pre[pre[x]]==goal) Rotate(x,ch[pre[x]][0]==x); else{ int y=pre[x],z=pre[y],f=(ch[z][0]==y); if(ch[y][f]==x) Rotate(x,!f),Rotate(x,f); else Rotate(y,f),Rotate(x,f); } } PushUp(x); if(goal==0) root=x; } inline void RotateTo(int k,int goal) {//将第k个数旋转到goal下面 int x=root; //cout<<k<<endl; PushDown(x); k++; //由于加入了两个边界结点 所以应为k+1位 while(sz[ch[x][0]]!=k-1) { if(k-1<sz[ch[x][0]]) x=ch[x][0]; else k-=(sz[ch[x][0]]+1), x=ch[x][1]; PushDown(x); } //if(k==1)cout<<x<<endl; Splay(x,goal); } inline void Delete(int x) {//把以x为祖先结点删掉放进内存池,回收内存 int fa=pre[x],head=0,tail=0; for(que[tail++]=x;head<tail;head++){ sta[top2++]=que[head]; if(ch[que[head]][0]) que[tail++]=ch[que[head]][0]; if(ch[que[head]][1]) que[tail++]=ch[que[head]][1]; } ch[fa][ch[fa][1]==x]=0; while(fa!=root) PushUp(fa),fa=pre[fa]; PushUp(root); } inline int pred(int x){//在x的子树中找x的前驱 PushDown(x); int y=ch[x][0]; PushDown(y); while(ch[y][1]) y=ch[y][1],PushDown(y); return y; } inline int succ(int x){//在x的子树中找x的后继 PushDown(x); int y=ch[x][1]; PushDown(y); while(ch[y][0]) y=ch[y][0],PushDown(y); return y; } void shuchu(int x){ //cout<<"结点 "<<x<<" 左结点 "<<ch[x][0]<<" 右结点 "<<ch[x][1]<<" 值 "<<val[x]<<endl; if(ch[x][0])shuchu(ch[x][0]); if(ch[x][1])shuchu(ch[x][1]); } //以上一般不修改////////////////////////////////////////////////// inline void NewNode(int &x,int c) { //需再处理pre[x] if(top2) x=sta[--top2];//用栈手动压的内存池 else x=++top1; ch[x][0]=ch[x][1]=0; sz[x]=1; val[x]=Min[x]=c; // add[x]=rev[x]=0; // } inline void makeTree(int &x,int l,int r,int arr[],int father){ if(l>r) return; int m=(l+r)>>1; NewNode(x,arr[m]); //num[m]权值改成题目所需的 makeTree(ch[x][0],l,m-1,arr,x); makeTree(ch[x][1],m+1,r,arr,x); pre[x]=father; PushUp(x); } inline void init(int n) { ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; root=top1=top2=0; add[0]=rev[0]=0; // val[0]=Min[0]=vaf; //为了方便处理边界,加两个边界顶点 NewNode(root,vaf); // NewNode(ch[root][1],vaf); // pre[top1]=root; sz[root]=2; makeTree(keyTree,1,n,num,ch[root][1]); PushUp(ch[root][1]); PushUp(root); } inline void PushDown(int x) { if(x==0) return; int l=ch[x][0],r=ch[x][1]; if(rev[x]){ rev[x]^=1; if(l) rev[ch[x][0]]^=1; if(r) rev[ch[x][1]]^=1; swap(ch[x][0],ch[x][1]); //int t=l; ch[x][0]=r; ch[x][1]=t; } if(add[x]){ if(l) add[l]+=add[x],val[l]+=add[x],Min[l]+=add[x]; if(r) add[r]+=add[x],val[r]+=add[x],Min[r]+=add[x]; add[x]=0; } } inline void PushUp(int x) { sz[x]=1+sz[ch[x][0]]+sz[ch[x][1]];//sz[0]==0 int l=ch[x][0],r=ch[x][1]; //Min[x]=Min[l]<Min[r]?Min[l]:Min[r]; //Min[x]=Min[x]<val[x]?Min[x]:val[x]; Min[x]=min(Min[l],Min[r]); Min[x]=min(Min[x],val[x]); } inline void Add(int a,int b,int d){ RotateTo(a-1,0); RotateTo(b+1,root); //cout<<val[root]<<' '<<val[ch[root][1]]<<' '<<Min[root]<<' '<<Min[ch[root][1]]<<endl; add[keyTree]+=d; val[keyTree]+=d; Min[keyTree]+=d; PushUp(ch[root][1]); PushUp(root); } inline void reverse(int a,int b){ RotateTo(a-1,0); RotateTo(b+1,root); rev[keyTree]^=1; //翻转不能直接 =1 } inline void revolve(int a,int b,int d){ //shuchu(root);cout<<endl; //d=(d%(b-a+1)+2*(b-a+1))%(b-a+1); d=d%(b-a+1); RotateTo(b-d,0); RotateTo(b+1,root); //shuchu(root);cout<<endl; PushDown(keyTree); int key=keyTree; keyTree=0; PushUp(ch[root][1]); PushUp(root); RotateTo(a-1,0); RotateTo(a,root); keyTree=key; if(key) pre[key]=ch[root][1]; PushUp(ch[root][1]); PushUp(root); } inline void insert(int a,int b){ RotateTo(a,0); RotateTo(a+1,root); NewNode(keyTree,b); pre[keyTree]=ch[root][1]; PushUp(ch[root][1]); PushUp(root); } inline void delet(int a){ RotateTo(a-1,0); RotateTo(a+1,root); Delete(keyTree); } inline void query(int a,int b){ RotateTo(a-1,0); RotateTo(b+1,root); printf("%d\n",Min[keyTree]); } int num[MaxN]; int val[MaxN]; int add[MaxN]; int Min[MaxN]; int rev[MaxN]; }spt; int main() { int n , m; int a,b,d; char c[10]; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&spt.num[i]); spt.init(n); scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%c",&c[0]); while(c[0]<'A'||c[0]>'Z') scanf("%c",&c[0]); scanf("%s",c+1); if(c[0]=='A'){ scanf("%d%d%d",&a,&b,&d); spt.Add(a,b,d); } else if(c[0]=='R'&&c[3]=='E'){scanf("%d%d",&a,&b); spt.reverse(a,b); } else if(c[0]=='R'){ scanf("%d%d%d",&a,&b,&d); spt.revolve(a,b,d); } else if(c[0]=='I'){ scanf("%d%d",&a,&b); spt.insert(a,b); } else if(c[0]=='D'){ scanf("%d",&a); spt.delet(a); } else if(c[0]=='M'){ scanf("%d%d",&a,&b); spt.query(a,b); } } return 0; }