[POJ3580]SuperMemo
Description
给出一个初始序列A1,A2,...,An,要求你编写程序支持如下操作:
- ADD x y D:给子序列Ax...Ay的每个元素都加上D。例如对1,2, 3,4,5执行"ADD 2 4 1" 会得到1,3,4,5,5。
- REVERSE x y:将子序列Ax...Ay翻转。例如对1,2,3,4,5执行"REVERSE 2 4"会得到1,4,3,2,5。
- REVOLVE x y T:将子序列Ax...Ay旋转T个单位。例如,对1,2,3,4,5执行"REVOLVE 2 4 2"会得到1,3,4,2,5。
- INSERT x P:在Ax后插入P。例如,对1,2,3,4,5执行"INSERT 2 4"会得到1,2,4,3,4,5。
- DELETE x:删去Ax。例如,对1,2,3,4,5执行"DELETE 2"会得到1,3,4,5。
- MIN x y:查询子序列Ax...Ay中的最小元素。例如,对于序列1, 2,3,4,5,询问"MIN 2 4"的返回应为2。
Input
第一行包含一个整数n,表示初始序列的长度。
以下n行每行包含一个整数,描述初始的序列。
接下来一行包含一个整数m,表示操作的数目。以下m行每行描述一个操作。n,m<=10^6
Output
对于所有"MIN"操作,输出正确的答案,每行一个。
Sample Input
5
1
2
3
4
5
2
ADD 2 4 1
MIN 4 5
Sample Output
5
跟[NOI2005]维修数列差不多,插入删除什么的都不用建树了,查找只要找MIN,除了REVOLVE麻烦点之外,其余并不难
找前驱后继的时候要记得pushdown,被坑了。。。
/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x3fffffff
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
int x=0,f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x>=10) print(x/10);
putchar(x%10+'0');
}
const int N=1e6;
int stack[N+10],top,v[N+10];
struct Splay{
#define T(x) (tree[f[x]][1]==x)
#define ls(x) tree[x][0]
#define rs(x) tree[x][1]
int tree[N+10][2],f[N+10],size[N+10],val[N+10],Min[N+10],cnt[N+10];
bool rev[N+10];
int root,len;
void rev_tag(int x){
if (!x) return;
swap(ls(x),rs(x));
rev[x]^=1;
}
void cnt_tag(int x,int v){
if (!x) return;
cnt[x]+=v,val[x]+=v,Min[x]+=v;
}
void pushdown(int x){
if (cnt[x]){
cnt_tag(ls(x),cnt[x]);
cnt_tag(rs(x),cnt[x]);
cnt[x]=0;
}
if (rev[x]){
rev_tag(ls(x));
rev_tag(rs(x));
rev[x]=0;
}
}
void updata(int x){
size[x]=size[ls(x)]+size[rs(x)]+1;
Min[x]=val[x];
if (ls(x)) Min[x]=min(Min[x],Min[ls(x)]);
if (rs(x)) Min[x]=min(Min[x],Min[rs(x)]);
}
int get(){
int x;
x=top?stack[top--]:++len;
val[x]=Min[x]=inf;
ls(x)=rs(x)=f[x]=0;
size[x]=1;
cnt[x]=rev[x]=0;
return x;
}
void build(int fa,int l,int r,int &x){
if (l>r) return;
int mid=(l+r)>>1;
x=get(),f[x]=fa,val[x]=Min[x]=v[mid];
build(x,l,mid-1,ls(x)),
build(x,mid+1,r,rs(x));
updata(x);
}
void init(int n){
val[0]=Min[0]=inf;
root=1,len=2;
rs(1)=size[1]=2,Min[1]=val[1]=inf;
f[2] =size[2]=1,Min[2]=val[2]=inf;
for (int i=1;i<=n;i++) v[i]=read();
build(2,1,n,ls(2));
updata(2),updata(1);
}
void move(int x){
pushdown(x);
int fa=f[x],son=tree[x][T(x)^1];
tree[x][T(x)^1]=fa;
tree[fa][T(x)]=son;
if (son) f[son]=fa;
f[x]=f[fa];
if (f[x]) tree[f[x]][T(fa)]=x;
f[fa]=x;
updata(fa),updata(x);
}
void splay(int x){
while (f[x]){
if (f[f[x]]) T(x)==T(f[x])?move(f[x]):move(x);
move(x);
}
root=x;
}
int find(int x,int i){
pushdown(i);
if (size[ls(i)]+1==x) return i;
if (x<=size[ls(i)]) return find(x,ls(i));
return find(x-size[ls(i)]-1,rs(i));
}
int get_suc(){
int x=rs(root);
pushdown(x);
while (ls(x)) pushdown(x),x=ls(x);
return x;
}
void insert(){
int x=read(),v=read(),t=get();
x=find(x+1,root),splay(x);
splay(get_suc());
f[rs(x)=t]=x;
val[t]=Min[t]=v;
updata(x),updata(root);
}
void ADD(){
int x=read(),y=read(),v=read();
x=find(x,root),splay(x);
y=find(y+2,root),splay(y);
if (f[x]!=root) move(x);
cnt_tag(rs(x),v);
updata(x),updata(y);
}
void filp(){
int x=read(),y=read();
x=find(x,root),splay(x);
y=find(y+2,root),splay(y);
if (f[x]!=root) move(x);
rev_tag(rs(x));
}
void Delete(){
int x=read(),y=x;
x=find(x,root),splay(x);
y=find(y+2,root),splay(y);
if (f[x]!=root) move(x);
stack[++top]=rs(x);
f[rs(x)]=0,rs(x)=0;
updata(x),updata(y);
}
void revolve(){
int l=read(),y=read(),len=y-l+1,t=read()%len,x=y-t+1;
if (!t) return;
x=find(x,root),splay(x);
y=find(y+2,root),splay(y);
if (f[x]!=root) move(x);
int son=rs(x);
f[rs(x)]=0,rs(x)=0;
updata(x),updata(y);
l=find(l,root),splay(l);
splay(get_suc());
rs(l)=son,f[son]=l;
updata(l),updata(root);
}
void query(){
int x=read(),y=read();
x=find(x,root),splay(x);
y=find(y+2,root),splay(y);
if (f[x]!=root) move(x);
printf("%d\n",Min[rs(x)]);
}
}T;
char s[10];
int main(){
int n=read();
T.init(n);
int m=read();
for (int i=1;i<=m;i++){
memset(s,0,sizeof(s));
scanf("%s",s);
if (s[0]=='A') T.ADD();
if (s[0]=='M') T.query();
if (s[0]=='I') T.insert();
if (s[0]=='D') T.Delete();
if (s[5]=='S') T.filp();
if (s[5]=='V') T.revolve();
}
return 0;
}