poj3580 SuperMemo (Splay+区间内向一个方向移动)
来源:互联网 发布:提前还房贷 知乎 编辑:程序博客网 时间:2024/04/28 05:37
Description
Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game. At first, the host tells the participant a sequence of numbers, {A1, A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:
- ADD x y D: Add D to each number in sub-sequence {Ax ... Ay}. For example, performing "ADD 2 4 1" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5, 5}
- REVERSE x y: reverse the sub-sequence {Ax ... Ay}. For example, performing "REVERSE 2 4" on {1, 2, 3, 4, 5} results in {1, 4, 3, 2, 5}
- REVOLVE x y T: rotate sub-sequence {Ax ... Ay} T times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
- INSERT x P: insert P after Ax. For example, performing "INSERT 2 4" on {1, 2, 3, 4, 5} results in {1, 2, 4, 3, 4, 5}
- DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
- MIN x y: query the participant what is the minimum number in sub-sequence {Ax ... Ay}. For example, the correct answer to "MIN 2 4" on {1, 2, 3, 4, 5} is 2
To make the show more interesting, the participant is granted a chance to turn to someone else that means when Jackson feels difficult in answering a query he may call you for help. You task is to watch the TV show and write a program giving the correct answer to each query in order to assist Jackson whenever he calls.
Input
The first line contains n (n ≤ 100000).
The following n lines describe the sequence.
Then follows M (M ≤ 100000), the numbers of operations and queries.
The following M lines describe the operations and queries.
Output
For each "MIN" query, output the correct answer.
Sample Input
51 2 3 4 52ADD 2 4 1MIN 4 5
Sample Output
5
题意:给你n个数组成的一个序列,让你写一个数据结构支持下列操作:1.区间[x,y]增加c 2.区间[x,y]翻转 3.区间[x,y]向右移动c次,如1 2 3 4 5向右移动2次就变成4 5 1 2 3。4.在第x个数后插入c 5.删除第x个数 6.求出区间[x,y]内的最小值。
思路:要维护rev[],mx[],add[]分别表示旋转标记,最小值以及成段增加的标记,然后这题和其他题不用的地方在于多了一个区间内移动的操作,我们要先求出c被y-x+1除后的余数,如果为0就不变,如果不为0,那么画图可以看出这个操作等价于把[y-c+1,y]移到[x,y-c]这个区间的前面,然后就可以直接做了。
#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<vector>#include<map>#include<set>#include<string>#include<bitset>#include<algorithm>using namespace std;typedef long long ll;typedef long double ldb;#define inf 99999999#define pi acos(-1.0)#define Key_value ch[ch[rt][1]][0]#define maxn 1000010int n;int cnt,rt;int pre[maxn],ch[maxn][2],sz[maxn],rev[maxn],zhi[maxn],mx[maxn],add[maxn];int b[maxn],tot2;//内存池和容量int a[maxn];void update_rev(int x){ if(!x)return; //!!! rev[x]^=1; swap(ch[x][0],ch[x][1]);}void update_add(int x,int value){ zhi[x]+=value; add[x]+=value; mx[x]+=value;}void pushdown(int x){ if(rev[x]){ update_rev(ch[x][0]); update_rev(ch[x][1]); rev[x]=0; } if(add[x]){ update_add(ch[x][0],add[x]); update_add(ch[x][1],add[x]); add[x]=0; }}void pushup(int x){ int t=zhi[x]; if(ch[x][0])t=min(t,mx[ch[x][0] ]); if(ch[x][1])t=min(t,mx[ch[x][1] ]); mx[x]=t; sz[x]=sz[ch[x][0] ]+sz[ch[x][1] ]+1;}void Treavel(int x){ if(x) { pushdown(x); Treavel(ch[x][0]); printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d zhi = %2d minx=%2d add=%2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],zhi[x],mx[x],add[x]); Treavel(ch[x][1]); }}void debug(){ printf("root:%d\n",rt); Treavel(rt);}void newnode(int &x,int father,int value){ if(tot2)x=b[tot2--]; else x=++cnt; pre[x]=father;ch[x][0]=ch[x][1]=0;sz[x]=1;rev[x]=0;zhi[x]=value;mx[x]=value;add[x]=0;}void build(int &x,int l,int r,int father){ if(l>r)return; int mid=(l+r)/2; newnode(x,father,a[mid]); build(ch[x][0],l,mid-1,x); build(ch[x][1],mid+1,r,x); pushup(x);}void init(){ cnt=rt=tot2=0; pre[0]=ch[0][0]=ch[0][1]=sz[0]=rev[0]=zhi[0]=mx[0]=add[0]=0; newnode(rt,0,-1); newnode(ch[rt][1],rt,-1); build(Key_value,1,n,ch[rt][1]); pushup(ch[rt][1]); pushup(rt);}void rotate(int x,int p){ int y=pre[x]; pushdown(y);pushdown(x); ch[y][!p]=ch[x][p]; pre[ch[x][p] ]=y; if(pre[y])ch[pre[y] ][ch[pre[y] ][1]==y ]=x; pre[x]=pre[y]; ch[x][p]=y; pre[y]=x; pushup(y);pushup(x);}void splay(int x,int goal){ pushdown(x); while(pre[x]!=goal){ if(pre[pre[x] ]==goal){ pushdown(pre[x]);pushdown(x); rotate(x,ch[pre[x]][0]==x); } else{ int y=pre[x];int z=pre[y]; pushdown(z);pushdown(y);pushdown(x); int p=ch[pre[y] ][0]==y; if(ch[y][p]==x )rotate(x,!p); else rotate(y,p); rotate(x,p); } } if(goal==0)rt=x; pushup(x);}int get_kth(int x,int k){ int i,j; pushdown(x); int t=sz[ch[x][0] ]+1; if(t==k)return x; if(t<k)return get_kth(ch[x][1],k-t); return get_kth(ch[x][0],k);}void erase(int x){ if(x==0)return; //!!! b[++tot2]=x; erase(ch[x][0]); erase(ch[x][1]);}void Add(int x,int y,int c){ splay(get_kth(rt,x),0); splay(get_kth(rt,y+2),rt); update_add(Key_value,c); pushup(ch[rt][1]); pushup(rt);}void Reverse(int x,int y){ splay(get_kth(rt,x),0); splay(get_kth(rt,y+2),rt); update_rev(Key_value); pushup(ch[rt][1]); pushup(rt);}void Insert(int x,int value){ int i,j; splay(get_kth(rt,x+1),0); splay(get_kth(rt,x+2),rt); newnode(Key_value,ch[rt][1],value); pushup(ch[rt][1]); pushup(rt);}void Rotate(int x,int y,int c){ int len=y-x+1; c=(c%len+len)%len; if(c==0)return; splay(get_kth(rt,y-c+1),0); splay(get_kth(rt,y+2 ),rt); int tmp=Key_value; Key_value=0; pushup(ch[rt][1]); pushup(rt); splay(get_kth(rt,x),0 ); splay(get_kth(rt,x+1),rt); Key_value=tmp; pre[tmp]=ch[rt][1]; pushup(ch[rt][1]); pushup(rt);}void Delete(int pos,int tot){ splay(get_kth(rt,pos),0); splay(get_kth(rt,pos+tot+1),rt); erase(Key_value); Key_value=0; pushup(ch[rt][1]); pushup(rt);}int Get_min(int x,int y){ splay(get_kth(rt,x),0); splay(get_kth(rt,y+2),rt); return mx[Key_value];}int main(){ int m,i,j,pos,tot,c,d,e,f; char s[10]; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++){ scanf("%d",&a[i]); } scanf("%d",&m); init(); //debug(); for(i=1;i<=m;i++){ scanf("%s",s); if(s[0]=='A'){ scanf("%d%d%d",&c,&d,&e); Add(c,d,e); } if(s[0]=='R' && s[3]=='E'){ scanf("%d%d",&c,&d); Reverse(c,d); } if(s[0]=='R' && s[3]=='O'){ scanf("%d%d%d",&c,&d,&e); Rotate(c,d,e); } if(s[0]=='I'){ scanf("%d%d",&c,&d); Insert(c,d); } if(s[0]=='D'){ scanf("%d",&c); Delete(c,1); } if(s[0]=='M'){ scanf("%d%d",&c,&d); printf("%d\n",Get_min(c,d)); //printf("1\n"); } //debug(); } } return 0;}
- poj3580 SuperMemo (Splay+区间内向一个方向移动)
- POJ3580 SuperMemo(Splay的区间操作)
- 【poj3580】【splay】SuperMemo
- poj3580 SuperMemo (splay)
- POJ3580 SuperMemo (Splay)
- POJ3580 SuperMemo(Splay)
- poj3580 SuperMemo 伸展树 splay
- POJ3580 SuperMemo(区间树)
- poj3580:SuperMemo(块状链表/Splay)
- poj3580 SuperMemo
- SuperMemo POJ3580
- POJ3580 SuperMemo
- poj3580 SuperMemo
- POJ3580 SuperMemo
- 【poj3580】 SuperMemo
- 【Splay|Treap】poj3580 SuperMemo && bzoj1503 [noi2004]郁闷的出纳员
- POJ3580 SuperMemo (Splay Tree的各种操作)
- POJ 3580 SuperMemo Splay 区间维护
- 深入Java虚拟机学习笔记 - 垃圾收集器
- 【数塔】1002 数塔取数问题【51nod】
- Snapshot Instance 操作详解 - 每天5分钟玩转 OpenStack(36)
- 我学编程时犯的最大两个错误
- php中final关键字
- poj3580 SuperMemo (Splay+区间内向一个方向移动)
- 操作系统课程设计银行家算法
- 基于http方式的git服务器搭建
- 求整数N的二进制表示中1的个数
- JAVA-008类和对象
- DeDeCMS二次开发教程之程序安装
- 九度OJ 1348-数组中的逆序对【逆序对模板】
- c语言学习笔记11
- LeetCode-237.Delete Node in a Linked List