题目大意:维护一种数据结构,它支持以下功能:
1.ADD:从第x个点到第y个点每个点加z。
2.REVERSE:将序列的x到y翻转。
3.REVOLVE:处理序列x到y,把它的最后一个值放在第一个位置。重复这样的操作z次。
4.INSERT:在第x个数后面加入一个数p
5.DELETE:把序列第x个数删除。
6.MIN:求出序列x到y中的最小值。
思路:除了REVOLVE以外的操作都是SPLAY的常规操作,正常写就可以。REVOLVE也十分简单。只要算好两边端点的值,把它提到root->son[1]->son[0]上拿出来,再进行一些Splay操作,把刚才从树中取出的序列插入到树中就可以。
关于负数取模:REVOLVE中给出的值有可能是负的,只需要((a % MO) + MO) % MO就可以得到正确的正值
CODE:
#include
#include
#include
#include
#define MAX 100010 #define INF 0x3f3f3f3f using namespace std; struct Complex{ int val,size; int _min; Complex *father,*son[2]; int c; bool reverse; bool Check() { return father->son[1] == this; } void Combine(Complex *a,bool dir) { son[dir] = a; a->father = this; } void Reverse() { reverse ^= 1; swap(son[0],son[1]); } void Plus(int num) { val += num; c += num; _min += num; } }none,*nil = &none,*root; int cnt; int src[MAX]; char s[20]; void Pretreatment(); Complex *BuildTree(int l,int r); inline Complex *NewComplex(int val); Complex *Kth(Complex *a,int k); inline void PushUp(Complex *a); inline void PushDown(Complex *a); inline void Rotate(Complex *a,bool dir); inline void Splay(Complex *a,Complex *aim); inline void SplaySeg(int l,int r); int main() { Pretreatment(); cin >> cnt; for(int i = 1;i <= cnt; ++i) scanf("%d",&src[i]); src[0] = src[cnt + 1] = INF; root = BuildTree(0,cnt + 1); root->father = nil; cin >> cnt; for(int x,y,z,i = 1;i <= cnt; ++i) { scanf("%s",s); if(!strcmp(s,"ADD")) { scanf("%d%d%d",&x,&y,&z); SplaySeg(x,y); root->son[1]->son[0]->Plus(z); PushUp(root->son[1]),PushUp(root); } if(!strcmp(s,"REVERSE")) { scanf("%d%d",&x,&y); SplaySeg(x,y); root->son[1]->son[0]->Reverse(); } if(!strcmp(s,"REVOLVE")) { scanf("%d%d%d",&x,&y,&z); int cnt = y - x + 1; z = ((z % cnt) + cnt) % cnt; SplaySeg(y - z + 1,y); Complex *temp = root->son[1]->son[0]; root->son[1]->son[0]->father = nil; root->son[1]->son[0] = nil; PushUp(root->son[1]),PushUp(root); Splay(Kth(root,x),nil); Splay(Kth(root,x + 1),root); root->son[1]->Combine(temp,false); PushUp(root->son[1]),PushUp(root); } if(!strcmp(s,"INSERT")) { scanf("%d%d",&x,&y); Splay(Kth(root,x + 1),nil); Splay(Kth(root,x + 2),root); root->son[1]->Combine(NewComplex(y),false); PushUp(root->son[1]),PushUp(root); } if(!strcmp(s,"DELETE")) { scanf("%d",&x); SplaySeg(x,x); root->son[1]->son[0]->father = nil; root->son[1]->son[0] = nil; PushUp(root->son[1]),PushUp(root); } if(!strcmp(s,"MIN")) { scanf("%d%d",&x,&y); SplaySeg(x,y); printf("%d\n",root->son[1]->son[0]->_min); } } return 0; } void Pretreatment() { nil->son[0] = nil->son[1] = nil->father = nil; nil->_min = INF; } Complex *BuildTree(int l,int r) { if(l > r) return nil; int mid = (l + r) >> 1; Complex *re = NewComplex(src[mid]); re->Combine(BuildTree(l,mid - 1),false); re->Combine(BuildTree(mid + 1,r),true); PushUp(re); return re; } inline Complex *NewComplex(int val) { Complex *re = new Complex(); re->son[0] = re->son[1] = nil; re->reverse = false; re->c = 0; re->size = 1; re->_min = re->val = val; return re; } inline void PushUp(Complex *a) { if(a == nil) return ; a->size = a->son[0]->size + a->son[1]->size + 1; a->_min = min(a->val,min(a->son[0]->_min,a->son[1]->_min)); } inline void PushDown(Complex *a) { if(a == nil) return ; if(a->reverse) { if(a->son[0] != nil) a->son[0]->Reverse(); if(a->son[1] != nil) a->son[1]->Reverse(); a->reverse = false; } if(a->c) { if(a->son[0] != nil) a->son[0]->Plus(a->c); if(a->son[1] != nil) a->son[1]->Plus(a->c); a->c = 0; } } inline void Rotate(Complex *a,bool dir) { Complex *f = a->father; PushDown(f),PushDown(a); f->son[!dir] = a->son[dir]; f->son[!dir]->father = f; a->s