题目描述
给出一个初始序列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 ",mn[y]); root=merge(merge(x,y),z); } } }