分析
说实话一开始根本没想线段树,考虑到前面各种奇怪的操作,我想到的是splay
然后在查询卡壳了,不得已写了线段树
结果写爆了,样例死活过不去……最后交的链表暴力
正难则反,我们考虑做旋转和翻转时,我们不动数据结构本身,而是给输入的值做变换
旋转了k,相当于对称轴-k
而翻转,会影响三个:
对称轴的变换,会转为顺时针
查询和修改,会转为从对称轴往逆时针数,而且计算也要往逆时针数,要交换
然后不得不说这题细节真[嘟——]多
我还给自己挖了个细节跳:
CS的查询,说是从x节点往y节点顺时针计算不同的颜色端有多少个
我考虑到了x-1==y的情况,也就是把整个项链囊括在内,我以为这时候要减去x的颜色=y的颜色的情况
然鹅顺时针算出来的其实是一条链……
#include <iostream> #include <cstdio> #include <memory.h> #include <cstdlib> #define lson (x<<1) #define rson ((x<<1)+1) using namespace std; const int N=5e5+10; struct Seg { int l,r,cnt,p; }t[4*N]; int rt=1,rv[N]; int n,c,q,a[N],dcz,rev; void Update(int x) { t[x].l=t[lson].l,t[x].r=t[rson].r; t[x].cnt=t[lson].cnt+t[rson].cnt-(t[lson].r==t[rson].l); } void Pushdown(int x) { if (t[x].p) { t[lson].l=t[lson].r=t[rson].l=t[rson].r=t[lson].p=t[rson].p=t[x].p; t[lson].cnt=t[rson].cnt=1; t[x].p=0; } } void Build(int x,int l,int r) { if (l==r) { t[x].l=t[x].r=a[l]; rv[l]=x;t[x].cnt=1; return; } int mid=l+r>>1; Build(lson,l,mid); Build(rson,mid+1,r); Update(x); } void Color(int x,int l,int r,int ll,int rr,int k) { if (rr<l||r<l||r<ll) return; if (ll<=l&&r<=rr) { t[x].l=t[x].r=t[x].p=k; t[x].cnt=1; return; } int mid=l+r>>1; Pushdown(x); if (ll<=mid) Color(lson,l,mid,ll,rr,k); if (mid<rr) Color(rson,mid+1,r,ll,rr,k); Update(x); } int Query(int x,int l,int r,int ll,int rr) { if (rr<l||r<l||r<ll) return 0; if (ll<=l&&r<=rr) return t[x].cnt; int mid=l+r>>1,ans=0; int c1=0,c2=0; Pushdown(x); if (ll<=mid) c1=Query(lson,l,mid,ll,rr); if (mid<rr) c2=Query(rson,mid+1,r,ll,rr); if (c1&&c2) ans=c1+c2-(t[lson].r==t[rson].l); else ans=c1+c2; return ans; } int main() { scanf("%d%d",&n,&c);rev=1;dcz=1; for (int i=1;i<=n;i++) scanf("%d",&a[i]); Build(rt,1,n); for (scanf("%d",&q);q;q--) { char ord[3];int x,y,z; memset(ord,0,sizeof ord); scanf("%s",ord); switch (ord[0]) { case 'R':{ scanf("%d",&x); dcz=((dcz-rev*x)%n+n-1)%n+1; break; } case 'F':{ rev*=-1; break; } case 'S':{ scanf("%d%d",&x,&y); x=((dcz+rev*x-rev)%n+n-1)%n+1;y=((dcz+rev*y-rev)%n+n-1)%n+1; Query(rt,1,n,x,x);Query(rt,1,n,y,y); int a=t[rv[x]].l,b=t[rv[y]].l; Color(rt,1,n,x,x,b);Color(rt,1,n,y,y,a); break; } case 'P':{ scanf("%d%d%d",&x,&y,&z); x=((dcz+rev*x-rev)%n+n-1)%n+1;y=((dcz+rev*y-rev)%n+n-1)%n+1; if (rev<0) swap(x,y); if (x<=y) Color(rt,1,n,x,y,z); else Color(rt,1,n,x,n,z),Color(rt,1,n,1,y,z); break; } case 'C':{ x=1,y=n; if (ord[1]=='S') scanf("%d%d",&x,&y),x=((dcz+rev*x-rev)%n+n-1)%n+1,y=((dcz+rev*y-rev)%n+n-1)%n+1; if (rev<0&&ord[1]=='S') swap(x,y); if (ord[1]!='S') { int z=Query(rt,1,n,1,n); printf("%d ",z=z-((z!=1)?(t[rt].l==t[rt].r):0)); } else if (x<=y) printf("%d ",z=Query(rt,1,n,x,y)); else { int z=Query(rt,1,n,x,n)+Query(rt,1,n,1,y); printf("%d ",z=z-((z!=1)?(t[rt].l==t[rt].r):0)); } } } } }