6.查询一个区间内的最小值
/* POJ 3580 ,这道题需要的操作包括: 1.区间增加相同的数 2.区间反转 3.区间滚动 4.插入一个数 5.删除一个数 6.查询一个区间内的最小值 */ #include <cstdio> #include<algorithm> #include<iostream> using namespace std; #define keyTree (ch[ ch[root][1] ][0]) const int maxn = 2222222; const int inf=1<<30; struct SplayTree{ int sz[maxn]; int ch[maxn][2]; int pre[maxn]; int root , top1 , top2; int ss[maxn] ,que[maxn]; inline void Rotate(int x,int f) { int y = pre[x]; push_down(y); push_down(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; push_up(y); } inline void Splay(int x,int goal) { push_down(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]; int f = (ch[z][0] == y); if(ch[y][f] == x) { Rotate(x , !f) , Rotate(x , f); } else { Rotate(y , f) , Rotate(x , f); } } } if(goal == 0) root = x; push_up(x); } inline void RotateTo(int k,int goal) {///把第k位的数转到goal下边 int x = root; push_down(x); while(sz[ ch[x][0] ] != k){ if(k < sz[ ch[x][0] ]) { x = ch[x][0]; } else { k -= (sz[ ch[x][0] ] + 1); x = ch[x][1]; } push_down(x); } Splay(x,goal); } inline void erase(int x){///把以x为祖先结点删掉放进内存池,回收内存 int father = pre[x]; int head = 0 , tail = 0; //push_down(x); for (que[tail++] = x ; head < tail ; head ++) { ss[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[ father ][ ch[father][1] == x ] = 0; //push_up(father); } ///找前驱,即左子树的最右结点 int get_pre(int x){ int tmp=ch[x][0]; if(tmp==0) return inf; while(ch[tmp][1]) tmp=ch[tmp][1]; return val[tmp]; } ///找后继,即右子树的最左结点 int get_next(int x){ int tmp=ch[x][1]; if(tmp==0) return inf; while(ch[tmp][0]) tmp=ch[tmp][0]; return val[tmp]; } ///以上一般不修改////////////////////////////////////////////////////////////////////////////// void debug() {printf("%d\n",root);Treaval(root);} void Treaval(int x) { if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]); Treaval(ch[x][1]); } } ///以上Debug ///以下是题目的特定函数: inline void NewNode(int &x,int c,int fa) { if (top2) x = ss[--top2];///用栈手动压的内存池 else x = ++top1; ch[x][0] = ch[x][1] = 0; pre[x]=fa; sz[x] = 1; val[x] =mi[x]=c;///*这是题目特定函数*/ add[x] = rev[x]=0; } inline void Rev(int x){ if(!x)return; swap(ch[x][0],ch[x][1]); rev[x]^=1; } void Add(int x,int v) { if(!x) return; val[x]+=v; mi[x]+=v; add[x]+=v; } ///把延迟标记推到孩子 inline void push_down(int x) {///*这是题目特定函数*/ if(add[x]){ Add(ch[x][0],add[x]),Add(ch[x][1],add[x]); } if(rev[x]){ Rev(ch[x][0]); Rev(ch[x][1]); } add[x] = rev[x]=0; } ///把孩子状态更新上来 inline void push_up(int x) { sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ]; ///*这是题目特定函数*/ mi[x]=min(val[x],min(mi[ch[x][0]],mi[ch[x][1]])); } ///*初始化*/ inline void makeTree(int &x,int l,int r,int f) { if(l > r) return ; int m = (l + r)>>1; NewNode(x , num[m],f); ///*num[m]权值改成题目所需的*/ makeTree(ch[x][0] , l , m - 1 , x); makeTree(ch[x][1] , m + 1 , r , x); pre[x] = f; push_up(x); } inline void init(int n) {///*这是题目特定函数*/ ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0; add[0] = rev[0]=top2=top1 = 0; ///为了方便处理边界,加两个边界顶点 val[0]=mi[0]=inf; NewNode(root,-inf,0); NewNode(ch[root][1],inf,root); // pre[top1] = 0; sz[root] = 2; for (int i = 1 ;i <=n ; i ++) scanf("%d",&num[i]); makeTree(keyTree , 1 , n , ch[root][1]); push_up(ch[root][1]); push_up(root); } ///*add 更新*/ inline void update(int l,int r,int c) {///*这是题目特定函数*/ RotateTo(l-1,0); RotateTo(r+1,root); add[ keyTree ] += c; mi[keyTree]+=c; val[keyTree]+=c; } ///删除 inline void del(int pos) { RotateTo(pos-1,0); RotateTo(pos+1,root); keyTree=0; push_up(ch[root][1]); push_up(root); } ///滚动 inline void revolve(int l,int r,int num) { num%=(r-l+1); num=(num+(r-l+1))%(r-l+1); if(!num) return; RotateTo(r-num,0); RotateTo(r+1,root); int x=keyTree; keyTree=0; push_up(ch[root][1]); push_up(root); RotateTo(l-1,0); RotateTo(l,root); keyTree=x; pre[keyTree]=ch[root][1]; push_up(ch[root][1]); push_up(root); } ///插入 inline void insert(int pos,int num) { RotateTo(pos,0); RotateTo(pos+1,root); NewNode(keyTree,num,ch[root][1]); push_up(ch[root][1]); push_up(root); } ///翻转 inline void revese(int l,int r) { RotateTo(l-1 , 0); RotateTo(r+1 , root); Rev(keyTree); } ///*询问*/ inline void getmin(int l,int r) { RotateTo(l-1 , 0); RotateTo(r+1 , root); printf("%d\n",mi[keyTree]); } ///*这是题目特定变量*/ int num[maxn]; int val[maxn]; int add[maxn]; int mi[maxn] ; int rev[maxn]; }spt; int main() { char op[10]; int l,r,c,pos,num,i,n,m; // freopen("//media/学习/ACM/input.txt","r",stdin); while(scanf("%d",&n)!=EOF){ spt.init(n); scanf("%d",&m); while(m--){ scanf("%s",op); if(op[0]=='I'){ scanf("%d%d",&pos,&num); spt.insert(pos,num); } else if(op[0]=='D'){ scanf("%d",&pos); spt.del(pos); } else if(op[0]=='A'){ scanf("%d%d%d",&l,&r,&c); if(l>r) swap(l,r); spt.update(l,r,c); // spt.debug(); } else if(op[0]=='R'&&op[3]=='E'){ scanf("%d%d",&l,&r); if(l>r) swap(l,r); spt.revese(l,r); } else if(op[0]=='M'){ scanf("%d%d",&l,&r); if(l>r) swap(l,r); spt.getmin(l,r); } else{ scanf("%d%d%d",&l,&r,&c); if(l>r) swap(l,r); spt.revolve(l,r,c); } } } return 0; }