题目
https://www.luogu.org/problemnew/show/P4130
解题思路
S
p
l
a
y
不
会
\color{red}Splay不会
Splay不会,那就正经的打线段树。
这道题目的后4问,就是纯正的线段树。
对于前两问,其实只是改变了每一个端点的位置,但没有改变他们的顺序,所以我们可以记录下他们的翻转次数和旋转次数,查询时倒推回去就可以了。
细节很多。
比如打函数名的时候,注意 s w a p swap swap是常用库中的定义函数,尽量不要重复。
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std;
const int N=500010;
int n,m,flag,Q,sum,b[N]; char ch[5];
struct node{
int l,r,lv,rv,cn,la;
}a[N*4];
inline int read(){
int p=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) p=p*10+c-48,c=getchar();
return p;
}
void up(int x){
a[x].cn=a[x*2].cn+a[x*2+1].cn;
if (a[x*2].rv==a[x*2+1].lv) a[x].cn--;
a[x].lv=a[x*2].lv,a[x].rv=a[x*2+1].rv;
}
void pushlazy(int x){
if (a[x].la){
a[x*2].lv=a[x*2].rv=a[x*2].la=a[x].la;
a[x*2+1].lv=a[x*2+1].rv=a[x*2+1].la=a[x].la;
a[x*2].cn=a[x*2+1].cn=1;
a[x].la=0;
}
}
void build(int x){
if (a[x].l==a[x].r){
a[x].lv=a[x].rv=b[a[x].l]; a[x].cn=1; return;
}
int mid=(a[x].l+a[x].r)>>1;
a[x*2].l=a[x].l,a[x*2].r=mid;
a[x*2+1].l=mid+1,a[x*2+1].r=a[x].r;
build(x*2),build(x*2+1); up(x);
}
int find(int x,int k){
if (a[x].l==a[x].r) return a[x].lv;
pushlazy(x);
int mid=(a[x].l+a[x].r)>>1;
if (k<=mid) find(x*2,k); else find(x*2+1,k);
}
void change(int x,int k,int val){
if (a[x].l==k&&a[x].r==k){
a[x].lv=a[x].rv=val; a[x].cn=1; return;
}
pushlazy(x);
int mid=(a[x].l+a[x].r)>>1;
if (k<=mid) change(x*2,k,val); else change(x*2+1,k,val);
up(x);
}
void changes(int x,int l,int r,int val){
if (a[x].l==l&&a[x].r==r) {
a[x].lv=a[x].rv=a[x].la=val; a[x].cn=1; return;
}
if (a[x].l==a[x].r) return;
pushlazy(x);
int mid=(a[x].l+a[x].r)>>1;
if (r<=mid) changes(x*2,l,r,val);
else if (l>mid) changes(x*2+1,l,r,val);
else changes(x*2,l,mid,val),changes(x*2+1,mid+1,r,val);
up(x);
}
void Swap(int x,int y){
int qx=find(1,x),qy=find(1,y);
change(1,y,qx),change(1,x,qy);
}
int ask(int x,int l,int r){
if (a[x].l==l&&a[x].r==r) return a[x].cn;
pushlazy(x);
int mid=(a[x].l+a[x].r)>>1;
if (r<=mid) return ask(x*2,l,r);
if (l>mid) return ask(x*2+1,l,r);
int ans=ask(x*2,l,mid)+ask(x*2+1,mid+1,r);
if (a[x*2].rv==a[x*2+1].lv) ans--;
return ans;
}
int get(){
int x=read();
if (flag) x=n-x+2;
return ((x-sum)%n+2*n-1)%n+1;
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
rep(i,1,n) b[i]=read();
a[1].l=1,a[1].r=n;
build(1); Q=read();
int x,y,k;
while (Q--){
scanf("%s",ch);
if (ch[0]=='R') {
k=read();
if (flag) sum-=k; else sum+=k;
}
if (ch[0]=='F') flag^=1;
if (ch[0]=='S') {
x=get(),y=get();
Swap(x,y);
}
if (ch[0]=='P') {
x=get(),y=get(),k=read();
if (flag) swap(x,y);
if (x<=y) changes(1,x,y,k);
else changes(1,1,y,k),changes(1,x,n,k);
}
if (ch[0]=='C'&&ch[1]=='S'){
x=get(),y=get();
if (flag) swap(x,y);
if (x<=y) printf("%d\n",ask(1,x,y)); else {
int ans=ask(1,1,y)+ask(1,x,n);
if (a[1].lv==a[1].rv) ans--;
printf("%d\n",ans);
}
}
if (ch[0]=='C' && ch[1]!='S')
{
int ans=ask(1,1,n);
if (a[1].lv==a[1].rv&&ans!=1) ans--;
printf("%d\n",ans);
}
}
}