这线段树还能不能好好用了╭(╯^╰)╮
然而Splay写起来太麻烦(虽然看起来好像很简单的样子,各种操作都支持)
于是还是滚回去用线段树,主要坑在旋转这个操作,因为线段树不能转。。。。所以只好让区间端点转一下了,所以每次操作的时候要先计算操作区间。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=500000+5;
inline int read(){
int x=0;char ch;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
struct data{int l,r,sum;};
struct seg{
int l,r,tag;
data c;
}tr[N*4];
bool rev;
int n,d;
void calc(int &x,int &y){
if(rev){
x=(n*2+2-d-x)%n;
y=(n*2+2-d-y)%n;
swap(x,y);
}else{
x=(x+n-d)%n;
y=(y+n-d)%n;
}
if(!x)x=n;if(!y)y=n;
}
inline data merge(data a,data b){
data tmp;
tmp.l=a.l;tmp.r=b.r;
tmp.sum=a.sum+b.sum;
if(a.r==b.l)tmp.sum--;
return tmp;
}
inline void pushup(int o){
tr[o].c=merge(tr[o<<1].c,tr[o<<1|1].c);
}
inline void pushdown(int o){
if(tr[o].tag&&tr[o].l!=tr[o].r){
tr[o<<1].tag=tr[o<<1|1].tag=tr[o<<1].c.l=tr[o<<1].c.r=tr[o<<1|1].c.l=tr[o<<1|1].c.r=tr[o].tag;
tr[o<<1].c.sum=tr[o<<1|1].c.sum=1;
tr[o].tag=0;
}
}
void build(int o,int l,int r){
tr[o].l=l;tr[o].r=r;
if(l==r){
tr[o].c.l=tr[o].c.r=read();
tr[o].c.sum=1;
}else{
int m=l+r>>1;
build(o<<1,l,m);build(o<<1|1,m+1,r);
pushup(o);
}
}
data query(int o,int a,int b){
pushdown(o);
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return tr[o].c;
else{
int m=l+r>>1;
if(b<=m)return query(o<<1,a,b);
else if(m<a)return query(o<<1|1,a,b);
else return merge(query(o<<1,a,m),query(o<<1|1,m+1,b));
}
}
void modify(int o,int a,int b,int v){
pushdown(o);
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r){
tr[o].c.l=tr[o].c.r=tr[o].tag=v;
tr[o].c.sum=1;
}else{
int m=l+r>>1;
if(b<=m)modify(o<<1,a,b,v);
else if(m<a)modify(o<<1|1,a,b,v);
else{
modify(o<<1,a,m,v);modify(o<<1|1,m+1,b,v);
}
pushup(o);
}
}
int main(){
int m;n=read();m=read();
build(1,1,n);
int x,y,v;
m=read();
char opt[10];
while(m--){
scanf("%s",opt);
if(opt[0]=='R'){
v=read();
if(rev)d=(d+n-v)%n;
else d=(d+v)%n;
}else if(opt[0]=='F')rev^=1;
else if(opt[0]=='S'){
x=read();y=read();
int a,b;data ans;
calc(x,y);
if(x<=y){
ans=query(1,x,y);
a=ans.l;b=ans.r;
}else{
ans=query(1,y,x);
a=ans.r;b=ans.l;
}
modify(1,x,x,b);modify(1,y,y,a);
}else if(opt[0]=='P'){
x=read();y=read();v=read();
calc(x,y);
if(x<=y)modify(1,x,y,v);
else{
modify(1,x,n,v);
modify(1,1,y,v);
}
}else if(opt[0]=='C'&&opt[1]=='S'){
x=read();y=read();
calc(x,y);
if(x<=y)printf("%d\n",query(1,x,y).sum);
else printf("%d\n",merge(query(1,x,n),query(1,1,y)).sum);
}else{
data ans=query(1,1,n);
int tmp=ans.sum;
if(ans.l==ans.r)tmp=max(tmp-1,1);
printf("%d\n",tmp);
}
}
return 0;
}