传送门
能不用splay坚决不用splay—–zyy
这道题如果没有旋转翻转操作的话就是一道区间修改,区间查询的线段树水题。
那么对于R,F操作应该怎么处理呢?
其实R,F操作之后珠子的相对位置没变
通俗来说就是一个珠子左右两边的珠子还是原来那两个
所以对于R,F操作我们只需要分别记录两个量即可:mov,rev
1.mov:表示当前整体顺时针移动了mov(即k变成k+mov)
输入R k,分两种情况:
没有被翻转过,mov+=k;
被翻转过,mov-=k
2.rev:表示当前是否被翻转过
输入F,直接rev^=1
然后线段树就水过了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define ls x*2
#define rs x*2+1
using namespace std;
struct node{int l,r,tag,lc,rc,sum;}t[2000005];
int n,cnt,m,x,y,z,ans,rev=0,mov=0,co[500005];
char ch[10];
void get(int &a){
if (rev) a=n-a+2;
a-=mov;
for (;a>n;a-=n);
for (;a<1;a+=n);
}
void pushup(int x){
t[x].lc=t[ls].lc;
t[x].rc=t[rs].rc;
t[x].sum=t[ls].sum+t[rs].sum;
if (t[ls].rc==t[rs].lc) t[x].sum--;
}
void pushdown(int x){
if (!t[x].tag) return;
t[ls].tag=t[rs].tag=t[x].tag;
t[ls].lc=t[ls].rc=t[rs].lc=t[rs].rc=t[x].tag;
t[ls].sum=t[rs].sum=1;
t[x].tag=0;
}
node merge(node a,node b){
node tmp;
tmp.sum=a.sum+b.sum;
tmp.lc=a.lc; tmp.rc=b.rc;
if (a.rc==b.lc) tmp.sum--;
return tmp;
}
void build(int x,int l,int r){
t[x].l=l; t[x].r=r;
t[x].tag=0;
if (l==r){
t[x].lc=t[x].rc=t[x].tag=co[l];
t[x].sum=1;
return;
}
int mid=(l+r)/2;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(x);
}
int color(int x,int y){
int l=t[x].l,r=t[x].r,mid=(l+r)/2;
if (l==r) return t[x].lc;
pushdown(x);
if (y<=mid) return color(ls,y);
return color(rs,y);
}
void change(int x,int p,int q,int v){
int l=t[x].l,r=t[x].r,mid=(l+r)/2;
if (l==p&&r==q){
t[x].lc=t[x].rc=t[x].tag=v;
t[x].sum=1;
return;
}
pushdown(x);
if (q<=mid) change(ls,p,q,v);
else if (p>mid) change(rs,p,q,v);
else change(ls,p,mid,v),change(rs,mid+1,q,v);
pushup(x);
}
node ask(int x,int p,int q){
int l=t[x].l,r=t[x].r,mid=(l+r)/2;
if (l==p&&r==q) return t[x];
pushdown(x);
if (q<=mid) return ask(ls,p,q);
if (p>mid) return ask(rs,p,q);
return merge(ask(ls,p,mid),ask(rs,mid+1,q));
}
int main(){
scanf("%d%d",&n,&cnt);
for (int i=1;i<=n;i++) scanf("%d",&co[i]);
build(1,1,n);
scanf("%d",&m);
while (m--){
scanf("%s",ch);
if (ch[0]=='R'){
scanf("%d",&x);
if (rev) mov-=x; else mov+=x;
for (;mov>n;mov-=n);
for (;mov<0;mov+=n);
}
if (ch[0]=='F') rev^=1;
if (ch[0]=='S'){
scanf("%d%d",&x,&y);
get(x); get(y);
int xx=color(1,x),yy=color(1,y);
change(1,x,x,yy);
change(1,y,y,xx);
}
if (ch[0]=='P'){
scanf("%d%d%d",&x,&y,&z);
get(x); get(y);
if (rev) swap(x,y);
if (x>y) change(1,x,n,z),change(1,1,y,z);
else change(1,x,y,z);
}
if (ch[0]=='C'){
if (ch[1]=='S'){
scanf("%d%d",&x,&y);
get(x); get(y);
if (rev) swap(x,y);
if (x<=y){
ans=ask(1,x,y).sum;
if (x==1&&y==n&&ans>1&&t[1].lc==t[1].rc) ans--;
}
else{
ans=ask(1,x,n).sum+ask(1,1,y).sum;
if (t[1].lc==t[1].rc) ans--;
}
}
else{
ans=t[1].sum;
if (ans>1&&t[1].lc==t[1].rc) ans--;
}
printf("%d\n",ans);
}
}
}