题目描述
给出一个初始序列fA1;A2;:::Ang,要求你编写程序支持如下操作: 1. ADDxyD:给子序列fAx:::Ayg的每个元素都加上D。例如对f1,2, 3,4,5g执行"ADD 241" 会得到f1,3,4,5,5g。 2. REVERSExy:将子序列fAx:::Ayg翻转。例如对f1,2,3,4,5g执 行"REVERSE 24"会得到f1,4,3,2,5g。 3. REVOLVExyT:将子序列fAx:::Ayg旋转T个单位。例如, 对f1,2,3,4,5g执行"REVOLVE 242"会得到f1,3,4,2,5g。 4. INSERTxP:在Ax后插入P。例如,对f1,2,3,4,5g执行"INSERT 24"会得到f1,2,4,3,4,5g。 5. DELETEx:删去Ax。例如,对f1,2,3,4,5g执行"DELETE 2"会得 到f1,3,4,5g。 6. MINxy:查询子序列fAx:::Ayg中的最小元素。例如,对于序列f1, 2,3,4,5g,询问"MIN 24"的返回应为2。
输入
第一行包含一个整数n,表示初始序列的长度。 以下n行每行包含一个整数,描述初始的序列。 接下来一行包含一个整数m,表示操作的数目。 以下m行每行描述一个操作。
输出
对于所有"MIN"操作,输出正确的答案,每行一个。
样例输入
5
1
2
3
4
5
2
ADD 2 4 1
MIN 4 5
1
2
3
4
5
2
ADD 2 4 1
MIN 4 5
样例输出
5
提示
输入、输出以及中间运算结果均不会超过32位整数。
对于30%的数据,n;m 6 1000;
对于100%的数据,n;m 6 100000。
序列终结者加强版,注意旋转操作的T可能大于区间长因此要取模,其他操作比较常规,插入删除直接断裂开之后在中间删掉或者加入;区间操作将treap断裂成三段,对中间一段打标记即可,标记在遍历点时下传。
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int cnt;
int n,m;
int root;
int L,R,C;
int w,x,y,z;
char ch[16];
int a[300010];
int s[300010];
int r[300010];
int v[300010];
int mn[300010];
int ls[300010];
int rs[300010];
int size[300010];
int build(int val)
{int rt=++cnt;v[rt]=val;size[rt]=1;r[rt]=rand();mn[rt]=val;return rt;
}
void rotate(int rt)
{swap(ls[rt],rs[rt]);s[rt]^=1;
}
void add(int rt,int val)
{a[rt]+=val;mn[rt]+=val;v[rt]+=val;
}
void pushup(int rt)
{size[rt]=size[ls[rt]]+size[rs[rt]]+1;mn[rt]=v[rt];if(ls[rt]){mn[rt]=min(mn[rt],mn[ls[rt]]);}if(rs[rt]){mn[rt]=min(mn[rt],mn[rs[rt]]);}
}
void pushdown(int rt)
{if(s[rt]){if(ls[rt]){rotate(ls[rt]);}if(rs[rt]){rotate(rs[rt]);}s[rt]^=1;}if(a[rt]){if(ls[rt]){add(ls[rt],a[rt]);}if(rs[rt]){add(rs[rt],a[rt]);}a[rt]=0;}
}
int merge(int x,int y)
{if(!x||!y){return x+y;}pushdown(x);pushdown(y);if(r[x]<r[y]){rs[x]=merge(rs[x],y);pushup(x);return x;}else{ls[y]=merge(x,ls[y]);pushup(y);return y;}
}
void split(int rt,int k,int &x,int &y)
{if(!rt){x=y=0;return ;}pushdown(rt);if(size[ls[rt]]<k){x=rt;split(rs[rt],k-size[ls[rt]]-1,rs[x],y);}else{y=rt;split(ls[rt],k,x,ls[y]);}pushup(rt);
}
int main()
{srand(20020419);scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&x);root=merge(root,build(x));}scanf("%d",&m);while(m--){scanf("%s",ch);if(ch[0]=='A'){scanf("%d%d%d",&L,&R,&C);split(root,L-1,x,y);split(y,R-L+1,y,z);add(y,C);root=merge(merge(x,y),z);}else if(ch[0]=='R'&&ch[3]=='E'){scanf("%d%d",&L,&R);split(root,L-1,x,y);split(y,R-L+1,y,z);rotate(y);root=merge(merge(x,y),z);}else if(ch[0]=='R'&&ch[3]=='O'){scanf("%d%d%d",&L,&R,&C);C%=(R-L+1);if(C==0){continue;}C=(R-L+1)-C;split(root,L-1,x,y);split(y,R-L+1,y,z);split(y,C,y,w);root=merge(merge(x,merge(w,y)),z);}else if(ch[0]=='I'){scanf("%d%d",&L,&C);split(root,L,x,y);root=merge(merge(x,build(C)),y);}else if(ch[0]=='D'){scanf("%d%d",&L,&C);split(root,L-1,x,y);split(y,1,y,z);root=merge(x,z);}else{scanf("%d%d",&L,&R);split(root,L-1,x,y);split(y,R-L+1,y,z);printf("%d\n",mn[y]);root=merge(merge(x,y),z);}}
}