#include <bits/stdc++.h>
using namespace std;
int coltag[1919810<<2],a[1919810],n,c,len[1919810<<2],q,hd=1,dir=1;
struct SegTree{
int prt,lcol,rcol;
SegTree(int prt=0,int lcol=0,int rcol=0):
prt(prt),lcol(lcol),rcol(rcol){}
}t[1919810<<2];
SegTree pushup(SegTree lson,SegTree rson){
return SegTree(((lson.rcol==rson.lcol&&lson.rcol)?lson.prt+rson.prt-1:lson.prt+rson.prt),lson.lcol,rson.rcol);
}
inline void tag(int x,int col){
coltag[x]=col;
t[x]=SegTree(1,col,col);
}
void pushdown(int x){
if(coltag[x]){
tag(x<<1,coltag[x]);
tag(x<<1|1,coltag[x]);
coltag[x]=0;
}
}
void build(int x,int l,int r){
len[x]=r-l+1;
if(l==r){
t[x]=SegTree(1,a[l],a[l]);
return;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
t[x]=pushup(t[x<<1],t[x<<1|1]);
}
int findcol(int x,int l,int r,int pos){
if(l==r&&l==pos) return t[x].lcol;
pushdown(x);
int mid=(l+r)>>1;
if(mid>=pos) return findcol(x<<1,l,mid,pos);
else return findcol(x<<1|1,mid+1,r,pos);
}
void flatten(int x,int l,int r,int L,int R,int col){
if(L<=l&&r<=R){
tag(x,col);
return;
}
pushdown(x);
int mid=(l+r)>>1;
if(L<=mid) flatten(x<<1,l,mid,L,R,col);
if(R>mid) flatten(x<<1|1,mid+1,r,L,R,col);
t[x]=pushup(t[x<<1],t[x<<1|1]);
}
SegTree query(int x,int l,int r,int L,int R){
if(L<=l&&r<=R){
return t[x];
}
pushdown(x);
SegTree r1,r2,res;
r1=r2=SegTree();
int mid=(l+r)>>1;
if(L<=mid) r1=query(x<<1,l,mid,L,R);
if(R>mid) r2=query(x<<1|1,mid+1,r,L,R);
res=pushup(r1,r2);
//puts("-------------");
//printf("|%d_%d_%d\n",r1.prt,r1.lcol,r1.rcol);
//printf("|%d_%d_%d\n",r2.prt,r2.lcol,r2.rcol);
// printf("|%d_%d_%d\n",res.prt,res.lcol,res.rcol);
return res;
}
int main(){
scanf("%d%d",&n,&c);
for(int i=1;i<=n;++i){
scanf("%d",a+i);
a[i+n]=a[i];
}
int N=2*n;
build(1,1,N);
scanf("%d",&q);
while(q--){
string opt;
int i,j,x;
cin>>opt;
if(opt[0]=='R'){
scanf("%d",&i);
hd=((hd-1-dir*i)%n+n)%n+1;
//printf("hd=%d\n",hd);
}
else if(opt[0]=='F'){
dir=-dir;
//printf("dir=%d\n",dir);
}
else if(opt=="C"){
SegTree ans=query(1,1,N,1,N);
printf("%d\n",ans.prt/2);
}
else{
bool flag=false;
int _i,_j;
scanf("%d%d",&i,&j);
if(dir<0) swap(j,i);
i=((hd-1+dir*(i-1))%n+n)%n+1;
j=((hd-1+dir*(j-1))%n+n)%n+1;
_i=i+n;
_j=j+n;
if(i>j) flag=true;
if(opt[0]=='S'){
int coli=findcol(1,1,N,i),colj=findcol(1,1,N,j);
flatten(1,1,N,i,i,colj);
flatten(1,1,N,_i,_i,colj);
flatten(1,1,N,j,j,coli);
flatten(1,1,N,_j,_j,coli);
}
else if(opt[0]=='P'){
scanf("%d",&x);
if(flag){
flatten(1,1,N,i,_j,x);
flatten(1,1,N,_j,_i,x);
flatten(1,1,N,_i,N,x);
flatten(1,1,N,1,j,x);
}
else{
flatten(1,1,N,i,j,x);
flatten(1,1,N,_i,_j,x);
}
}
else{
SegTree ans;
if(flag){
ans=query(1,1,N,i,_j);
}
else{
ans=query(1,1,N,i,j);
}
printf("%d\n",ans.prt);
}
}
}
return 0;
}
思路:
用2n大小数组存环,dir和hd描述顶点和方向(是否翻转),线段树写法参考P2572第一篇题解。这2n大小数组的部分数/2即环的部分数。每次修改都会同步修改2n数组中与i、j表示相同位置的点_i、_j,根据dir以及i、j大小关系决定修改哪些区间。