BZOJ_1895_Pku3580 supermemo_Splay
Description
给出一个初始序列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。
Input
第一行包含一个整数n,表示初始序列的长度。 以下n行每行包含一个整数,描述初始的序列。 接下来一行包含一个整数m,表示操作的数目。 以下m行每行描述一个操作。
Output
对于所有"MIN"操作,输出正确的答案,每行一个。
Sample Input
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
Sample Output
5
HINT
输入、输出以及中间运算结果均不会超过32位整数。
对于30%的数据,n;m 6 1000;
对于100%的数据,n;m 6 100000。
splay裸题,操作稍微多了点。
旋转操作可以理解为进行三次区间翻转操作,这样就十分方便了。
注意旋转单位要mod区间长度。
具体实现在代码中:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 1200050 #define ls ch[p][0] #define rs ch[p][1] #define get(x) (ch[f[x]][1]==x) int ch[N][2],f[N],siz[N],turn[N],val[N],mn[N],rt; int a[N],n,add[N],sz,m,now; char opt[10]; void pushup(int p){ if(!p)return ; siz[p]=1; if(ls) siz[p]+=siz[ls]; if(rs) siz[p]+=siz[rs]; mn[p]=min(mn[ls],mn[rs]); mn[p]=min(mn[p],val[p]); } void pushdown(int p) { if(add[p]){ if(ls) mn[ls]+=add[p],val[ls]+=add[p],add[ls]+=add[p]; if(rs) mn[rs]+=add[p],val[rs]+=add[p],add[rs]+=add[p]; add[p]=0; } if(turn[p]){ swap(ls,rs); if(ls) turn[ls]^=1; if(rs) turn[rs]^=1; turn[p]=0; } } void rotate(int x) { int y=f[x],z=f[y],k=get(x); ch[y][k]=ch[x][!k];f[ch[y][k]]=y; ch[x][!k]=y;f[y]=x;f[x]=z; if(z) ch[z][ch[z][1]==y]=x; pushup(y);pushup(x); if(rt==y) rt=x; } void splay(int x,int y) { for(int fa;(fa=f[x])!=y;rotate(x)) if(f[fa]!=y) rotate((get(x)==get(fa)) ? fa : x); } int find(int x) { int p=rt; while(1) { pushdown(p); if(x<=siz[ls]) p=ls; else{ x-=siz[ls]+1; if(!x) return p; p=rs; } } } void addadd(int x,int p,int v) { x=find(x); p=find(p); splay(x,0); splay(p,rt); add[ls]+=v; mn[ls]+=v; val[ls]+=v; pushup(p);pushup(x); } void reverse(int x,int p) { x=find(x); p=find(p); splay(x,0); splay(p,rt); turn[ls]^=1; } void build(int fa,int l,int r) { if(l>r) return ; int mid=l+r>>1; ch[fa][mid>fa]=mid; f[mid]=fa; val[mid]=mn[mid]=a[mid-1]; build(mid,l,mid-1); build(mid,mid+1,r); pushup(mid); } void insert(int x,int v) { now++; int p=x+1; x=find(x); p=find(p); splay(x,0); splay(p,rt); ls=++sz; val[ls]=mn[ls]=v; f[ls]=p; siz[ls]=1; pushup(p);pushup(x); } void del(int x) { now--; int p=x+2; x=find(x); p=find(p); splay(x,0); splay(p,rt); ls=0; pushup(p);pushup(x); } int ask(int x,int p) { x=find(x); p=find(p); splay(x,0); splay(p,rt); return mn[ls]; } /*void print() { int p,i; for(i=1;i<=now;i++){ p=find(i); printf("p=%d val[p]=%d ",p,val[p]); } }*/ int main(){ //memset(mn,0x3f,sizeof(mn)); mn[0]=1<<30; scanf("%d",&n); int i,x,y,z; for(i=1;i<=n;i++) scanf("%d",&a[i]); build(0,1,n+2); sz=now=n+2; rt=n+3>>1; scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%s%d",opt,&x); if(opt[0]=='A') { scanf("%d%d",&y,&z); x++;y++; addadd(x-1,y+1,z); } else if(opt[0]=='R') { scanf("%d",&y); x++;y++; if(opt[3]=='E') { reverse(x-1,y+1); } else { scanf("%d",&z); z%=(y-x+1); if(z==0)continue; reverse(x-1,y+1); reverse(x-1,x+z); reverse(x+z-1,y+1); } } else if(opt[0]=='I') { scanf("%d",&y); x++; insert(x,y); } else if(opt[0]=='D') { x++; del(x-1); } else { scanf("%d",&y); x++;y++; printf("%d ",ask(x-1,y+1)); } } }