题意:有N个数字围成一个圈,有M个操作,操作类型有六种:(1)“add x",从当前指针位置开始的顺时针K2个数加上x。(2)"reverse",翻转,从当前指针指针位置开始的顺时针的K2个数。(3)"insert x",在当前指针位置的顺时候方向插入一个数x。(4)”delete“,删除当前指针所指的数。(5)"move x”,如果x=1,指针逆时针旋转,如果x=2,顺时针旋转。(6)“query",查询指针所指向的数的值。
Splay的作法就不说了。还可以有三个双端队列加两个标记搞定,方法,是第一个双端队列que1维护前K1个数,第二个que2维护第K1+1到第K2个数,第三个que3维护接下的数,标记add,表示que1和que2里的数要加上多少,标记head,表示que1是否被翻转过。
Splay(姿势1):
#include
#include
#include
#include
#include
#include
#include
#include
#include
Spaly(姿势2):
#include
#include
#include
using namespace std;
#define LL(x) (ch[x][0])
#define RR(x) (ch[x][1])
#define Kt (ch[ ch[Rt][1] ][0])
#define MID(a,b) (a+((b-a)>>1))
const int N=1e6+5;
int a[N/2];
int n,m,K1,K2,pos;
struct SplayTree
{
int Rt,top;
int sz[N],pre[N],ch[N][2];
bool flip[N];
int key[N],add[N];
inline void Link(int x,int y,int f)
{
pre[x]=y; if(y) ch[y][f]=x;
}
inline void Rotate(int x,int f)
{
int y=pre[x],z=pre[y];
PushDown(y); PushDown(x);
Link(x,z,RR(z)==y);
Link(ch[x][f],y,!f);
Link(y,x,f);
PushUp(y);
}
inline void Splay(int x,int goal)
{
while(pre[x]!=goal)
{
int y=pre[x],z=pre[y];
int cx=(LL(y)==x),cy=(LL(z)==y);
if(z==goal) Rotate(x,cx);
else
{
if(cx==cy) Rotate(y,cy);
else Rotate(x,cx);
Rotate(x,cy);
}
}
PushUp(x);
if(goal==0) Rt=x;
}
inline void Select(int K,int goal)
{
int x=Rt;
PushDown(x);
while(1)
{
if(sz[LL(x)]>=K) x=LL(x);
else if(1+sz[LL(x)]==K) break;
else K-=sz[LL(x)]+1,x=RR(x);
PushDown(x);
}
Splay(x,goal);
}
inline void fun_add(int x,int valu)
{
key[x]+=valu;
add[x]+=valu;
}
inline void fun_flip(int x)
{
flip[x]^=1;
swap(LL(x),RR(x));
}
inline void PushUp(int x)
{
sz[x]=1+sz[LL(x)]+sz[RR(x)];
}
inline void PushDown(int x)
{
if(add[x])
{
fun_add(LL(x),add[x]);
fun_add(RR(x),add[x]);
add[x]=0;
}
if(flip[x])
{
fun_flip(LL(x)); fun_flip(RR(x));
flip[x]=0;
}
}
inline void Add(int st,int ed,int valu)
{
Select(st-1,0); Select(ed+1,Rt);
fun_add(Kt,valu);
}
inline void Reverse(int st,int ed)
{
Select(st-1,0); Select(ed+1,Rt);
fun_flip(Kt);
}
inline void Insert(int pos,int valu)
{
Select(pos,0); Select(pos+1,Rt);
addNode(valu,Kt,RR(Rt));
PushUp(RR(Rt)); PushUp(Rt);
}
inline void Delete(int pos)
{
Select(pos-1,0); Select(pos+1,Rt);
Kt=0; PushUp(RR(Rt)); PushUp(Rt);
}
inline void Query(int pos)
{
Select(pos,0);
printf("%d\n",key[Rt]);
}
inline void Move(int len)
{
pos-=len;
Select(1,0); Select(2+len,Rt);
int r1=Kt; Kt=0;
PushUp(RR(Rt)); PushUp(Rt);
Select(sz[Rt]-1,0); Select(sz[Rt],Rt);
Link(r1,RR(Rt),0);
PushUp(RR(Rt)); PushUp(Rt);
}
inline void addNode(int valu,int &x,int f)
{
x=++top;
sz[x]=1; pre[x]=f; LL(x)=RR(x)=0;
key[x]=valu; add[x]=flip[x]=0;
}
void build(int lft,int rht,int &x,int f)
{
if(lft>rht) return;
int mid=MID(lft,rht);
addNode(a[mid],x,f);
build(lft,mid-1,LL(x),x);
build(mid+1,rht,RR(x),x);
PushUp(x);
}
void init()
{
Rt=top=0;
addNode(0,Rt,0); addNode(0,RR(Rt),Rt);
build(0,n-1,Kt,RR(Rt));
PushUp(RR(Rt)); PushUp(Rt);
}
// void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }
// void Travel(int x)
// {
// if(x==0) return;
// PushDown(x);
// Travel(LL(x));
// printf("node:%d,sz:%d,pre:%d,LL:%d,RR:%d,key:%d\n",
// x,sz[x],pre[x],LL(x),RR(x),key[x]);
// Travel(RR(x));
// }
}spt;
void deal(int &pos,int len)
{
if(pos<=1) pos=len-1;
if(pos>=len) pos=2;
}
int main()
{
freopen("in.txt","r",stdin);
int t_cnt=0;
while(scanf("%d%d%d%d",&n,&m,&K1,&K2)!=EOF)
{
if(n==0&&m==0&&K1==0&&K2==0) break;
for(int i=0;ilen) spt.Move(pos+K2-len);
spt.Add(pos,pos+K2-1,x);
}
else if(op[0]=='r')
{
if(pos+K1>=len) spt.Move(pos+K1-len);
spt.Reverse(pos,pos+K1-1);
}
else if(op[0]=='i')
{
scanf("%d",&x); spt.Insert(pos,x);
}
else if(op[0]=='d')
{
spt.Delete(pos);
deal(pos,spt.sz[spt.Rt]);
}
else if(op[0]=='m')
{
scanf("%d",&x);
if(x==1) pos--;
else pos++;
deal(pos,len);
}
else if(op[0]=='q') spt.Query(pos);
// spt.Debug();
}
}
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include