题意:有n个数排成环,m个操作1.当前位置后k2个加一个数,2当前位置后k1个翻转,3当前位置后面插入一个数,4删除当前位置的数,5将当前位置前移或后移6查询当前位置的权值
题解:splay裸题,唯一麻烦的是翻转操作,因为可能不连续,单独考虑即可
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
//#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define fin freopen("a.txt","r",stdin)
#define fout freopen("c.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
template<typename T>
inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>
inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}
using namespace std;
const double eps=1e-8;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=500000+10,maxn=200000+10,inf=0x3f3f3f3f;
int n;
struct Splay{
struct Node{
Node* ch[2];
int v,s;
int flip,lazy;
int cmp(int x)const{
int d = x - ch[0]->s;
if(d==1)return -1;
return d<=0 ? 0:1;
}
void maintain()
{
s = 1 + ch[0]->s + ch[1]->s;
}
void pushdown()
{
if(flip)
{
flip=0;
swap(ch[0],ch[1]);
ch[0]->flip = !(ch[0]->flip);
ch[1]->flip = !(ch[1]->flip);
}
if(lazy!=0)
{
if(ch[0]->s!=0)ch[0]->v+=lazy;
if(ch[1]->s!=0)ch[1]->v+=lazy;
ch[0]->lazy+=lazy;
ch[1]->lazy+=lazy;
lazy=0;
}
}
};
Node pp[N];
int cnt;
Node* null;
void Rotate(Node* &o,int d)
{
Node* k = o->ch[d^1];
o->ch[d^1] = k->ch[d];
k->ch[d] = o;
o->maintain();k->maintain();
o = k;
}
void splay(Node* &o,int k)
{
o->pushdown();
int d = o->cmp(k);
if(d==1)k -= o->ch[0]->s + 1;
if(d!=-1)
{
Node* p = o->ch[d];
p->pushdown();
int d2 = p->cmp(k);
int k2 = (d2==0 ? k:k-p->ch[0]->s-1);
if(d2!=-1)
{
splay(p->ch[d2],k2);
if(d==d2)Rotate(o,d^1);
else Rotate(o->ch[d],d);
}
Rotate(o,d^1);
}
}
Node* Merge(Node* left,Node* right)
{
splay(left,left->s);
left->ch[1] = right;
left->maintain();
return left;
}
void split(Node* o,int k,Node* &left,Node* &right)
{
splay(o,k);
right = o->ch[1];
o->ch[1] = null;
left = o;
left->maintain();
}
Node *root,*left,*right;
void init(int sz)
{
cnt=0;
null=&pp[++cnt];
null->s=0;
root=&pp[++cnt];
scanf("%d",&root->v);
root->flip=root->lazy=0;root->s=1;
root->ch[0]=root->ch[1]=null;
root->maintain();
Node* p;
for(int i=2;i<=sz;i++)
{
p=&pp[++cnt];
scanf("%d",&p->v);
p->s=p->flip=0;
p->lazy=0;
p->ch[0]=root,p->ch[1]=null;
root=p;
root->maintain();
}
}
void ins(int pos,int x)
{
Node *mid;mid=&pp[++cnt];
mid->v=x;
mid->flip=0,mid->lazy=0;
mid->ch[0]=mid->ch[1]=null;
mid->maintain();
if(pos==root->s)root=Merge(root,mid);
else
{
split(root,pos,left,right);
root=Merge(left,Merge(mid,right));
// print(root);
}
}
void del(int pos)
{
if(pos==1)
{
split(root,1,left,right);
root=right;
}
else if(pos==n)
{
split(root,pos-1,left,right);
root=left;
}
else
{
split(root,pos,left,right);
Node *mid;
split(left,pos-1,left,mid);
root=Merge(left,right);
}
}
int change(int l,int r,int x,int op)//1-add,2-rev,3-query
{
int ans=0;
if(l==1&&r==root->s)
{
if(op==1)
{
root->lazy+=x;
root->v+=x;
}
else if(op==2)root->flip^=1;
else ans=root->v;
}
else if(l==1&&r!=root->s)
{
split(root,r,left,right);
if(op==1)
{
left->lazy+=x;
left->v+=x;
}
else if(op==2)left->flip^=1;
else ans=left->v;
root=Merge(left,right);
}
else if(l!=1&&r==root->s)
{
split(root,l-1,left,right);
if(op==1)
{
right->lazy+=x;
right->v+=x;
}
else if(op==2)right->flip^=1;
else ans=right->v;
root=Merge(left,right);
}
else
{
split(root,r,left,right);
Node *mid;
split(left,l-1,left,mid);
if(op==1)
{
mid->lazy+=x;
mid->v+=x;
}
else if(op==2)mid->flip^=1;
else ans=mid->v;
root=Merge(left,Merge(mid,right));
}
return ans;
}
void rev(int l1,int r1,int l2,int r2)
{
// printf("%d %d %d %d
",l1,r1,l2,r2);
if(r1-l1==r2-l2)
{
split(root,l2-1,left,right);
Node *mid;
split(left,r1,left,mid);
left->flip^=1,right->flip^=1;
root=Merge(right,Merge(mid,left));
}
else if(r1-l1>r2-l2)
{
int len=r2-l2+1,te=r1-len+1;
// printf("%d %d
",len,te);
Node *mid1;Node *mid2;
split(root,l2-1,left,right);
split(left,r1,left,mid2);
split(left,te-1,left,mid1);
mid1->flip^=1;
left->flip^=1;right->flip^=1;
root=Merge(Merge(left,right),Merge(mid2,mid1));
}
else
{
int len=r1-l1+1,te=l2+len-1;
Node *mid1;Node *mid2;
split(root,te,left,right);
split(left,l2-1,left,mid2);
split(left,r1,left,mid1);
mid2->flip^=1;
left->flip^=1;right->flip^=1;
root=Merge(Merge(mid2,mid1),Merge(left,right));
}
}
void print(Node *o)
{
o->pushdown();
printf("%d %d %d++
",o->ch[0]->v,o->v,o->ch[1]->v);
if(o->ch[0]!=null)print(o->ch[0]);
if(o->ch[1]!=null)print(o->ch[1]);
}
}sp;
char op[10];
int main()
{
int cas=0,m,k1,k2;
while(~scanf("%d%d%d%d",&n,&m,&k1,&k2))
{
if(!n&&!m&&!k1&&!k2)break;
int now=1;
sp.init(n);
printf("Case #%d:
",++cas);
while(m--)
{
scanf("%s",op);
if(op[0]=='a')
{
int x;scanf("%d",&x);
if(now+k2-1>n)
{
sp.change(now,n,x,1);
sp.change(1,now+k2-n-1,x,1);
}
else sp.change(now,now+k2-1,x,1);
}
else if(op[0]=='r')
{
if(now+k1-1>n)sp.rev(1,now+k1-n-1,now,n);
else sp.change(now,now+k1-1,0,2);
}
else if(op[0]=='i')
{
int x;scanf("%d",&x);
sp.ins(now,x);n++;
}
else if(op[0]=='d')
{
sp.del(now);
if(now==n)now=1;
n--;
}
else if(op[0]=='m')
{
int x;scanf("%d",&x);
if(x==1)
{
now--;
if(now<=0)now=n;
}
else
{
now++;
if(now>n)now=1;
}
}
else printf("%d
",sp.change(now,now,0,3));
}
}
return 0;
}
/********************
5 100 3 4
1 2 3 4 5
move 1
reverse
query
********************/