题目大意:维护一个序列,提供一些操作:
1.将一个区间加上一个值
2.翻转一个区间
3.将一个区间内的数字旋转T次(每次旋转区间内每个元素向右移一位,最右一个移动到最左面去)
4.在一个元素后面插入一个数
5.删除某个元素
6.查询区间最小值
写过BZOJ那几道Splay之后这题就变得非常水了。。。只是有几个要点需要注意:
1.操作3的T可能大于区间长度 还可能是负的 所以一定要取模
2.操作3非常容易弄反 是把后T个数字移动到前面来 不是把前T个数字移动到后面去
4.空节点null的初值要设为极大值 0x3f不够大 直接设成2147483647比较好
5.下传标记的时候一定要特判节点是不是null 不然null会被加爆 切记!
6.看题解要认真仔细 比如说我的要点没有第三条 你看到了么
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x7fffffff
using namespace std;
struct abcd{
abcd *fa,*ls,*rs;
int siz,num,minnum;
int add_mark,rev_mark;
abcd(int x);
void Push_Up();
void Push_Down();
}*null=new abcd(INF),*root=null;
abcd :: abcd(int x)
{
fa=ls=rs=null;
siz=1;
if(x==INF)
siz=0;
num=minnum=x;
add_mark=rev_mark=0;
}
void abcd :: Push_Up()
{
siz=ls->siz+rs->siz+1;
minnum=min(ls->minnum,rs->minnum);
minnum=min(minnum,num);
}
void abcd :: Push_Down()
{
if(add_mark)
{
if(ls!=null)
{
ls->add_mark+=add_mark;
ls->num+=add_mark;
ls->minnum+=add_mark;
}
if(rs!=null)
{
rs->add_mark+=add_mark;
rs->num+=add_mark;
rs->minnum+=add_mark;
}
add_mark=0;
}
if(rev_mark)
{
ls->rev_mark^=1;
rs->rev_mark^=1;
swap(ls->ls,ls->rs);
swap(rs->ls,rs->rs);
rev_mark=0;
}
}
void Zig(abcd *x)
{
abcd *y=x->fa;
y->Push_Down();
x->Push_Down();
y->ls=x->rs;
x->rs->fa=y;
x->rs=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
if(y==root)
root=x;
}
void Zag(abcd *x)
{
abcd *y=x->fa;
y->Push_Down();
x->Push_Down();
y->rs=x->ls;
x->ls->fa=y;
x->ls=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
if(y==root)
root=x;
}
void Splay(abcd *x,abcd *Tar)
{
while(1)
{
abcd *y=x->fa,*z=y->fa;
if(y==Tar)
break;
if(z==Tar)
{
if(x==y->ls)Zig(x);
else Zag(x);
break;
}
if(x==y->ls)
{
if(y==z->ls)
Zig(y);
Zig(x);
}
else
{
if(y==z->rs)
Zag(y);
Zag(x);
}
}
x->Push_Up();
}
void Find(abcd *x,int y,abcd *z)
{
while(1)
{
x->Push_Down();
if(y<=x->ls->siz)
x=x->ls;
else
{
y-=x->ls->siz;
if(y==1)
break;
y--;
x=x->rs;
}
}
Splay(x,z);
}
void Insert(abcd *&x,int y,abcd *z)
{
if(x==null)
{
x=new abcd(y);
x->fa=z;
Splay(x,null);
return ;
}
x->Push_Down();
Insert(x->rs,y,x);
}
int n,m;
int main()
{
int i,x,y,z;
char p[10];
cin>>n;
Insert(root,19980402,null);
for(i=1;i<=n;i++)
scanf("%d",&x),Insert(root,x,null);
Insert(root,19980402,null);
cin>>m;
for(i=1;i<=m;i++)
{
scanf("%s",p);
if(p[0]=='A')
{
scanf("%d%d%d",&x,&y,&z);
Find(root,x,null);
Find(root,y+2,root);
abcd *temp=root->rs->ls;
temp->add_mark+=z;
temp->num+=z;
temp->minnum+=z;
}
else if(p[0]=='R'&&p[3]=='E')
{
scanf("%d%d",&x,&y);
Find(root,x,null);
Find(root,y+2,root);
abcd *temp=root->rs->ls;
temp->rev_mark^=1;
swap(temp->ls,temp->rs);
}
else if(p[0]=='R'&&p[3]=='O')
{
scanf("%d%d%d",&x,&y,&z);
z%=y-x+1;
z+=y-x+1;
z%=y-x+1;
if(!z)
continue;
Find(root,y-z+1,null);
Find(root,y+2,root);
abcd *temp=root->rs->ls;
root->rs->ls=null;
root->rs->Push_Up();
root->Push_Up();
Find(root,x,null);
Find(root,x+1,root);
root->rs->ls=temp;
temp->fa=root->rs;
root->rs->Push_Up();
root->Push_Up();
}
else if(p[0]=='I')
{
scanf("%d%d",&x,&y);
Find(root,x+1,null);
Find(root,x+2,root);
Insert(root->rs->ls,y,root->rs);
}
else if(p[0]=='D')
{
scanf("%d",&x);
Find(root,x,null);
Find(root,x+2,root);
root->rs->ls=null;
root->rs->Push_Up();
root->Push_Up();
}
else
{
scanf("%d%d",&x,&y);
Find(root,x,null);
Find(root,y+2,root);
printf("%d\n",root->rs->ls->minnum);
}
}
}