Description
T 公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖、款式多样、价格适中,广受青年人的喜爱。最近T 公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链。
该项链自助生产系统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的项链。该系统的硬件系统已经完成,而软件系统尚未开发,T 公司的人找到了正在参加全国信息学竞赛的你,你能帮助T 公司编写一个软件模拟系统吗?
一条项链包含N 个珠子,每个珠子的颜色是1, 2, …, c 中的一种。项链被固定在一个平板上,平板的某个位置被标记位置1,按顺时针方向其他位置被记为2,3,…,N。
你将要编写的软件系统应支持如下命令:
1.R k(0 < K < N) 意为Rotate k。将项链在平板上顺时针旋转k 个位置, 即原来处于位置1 的珠子将转至位置k+1,处于位置2 的珠子将转至位置k+2,依次类推。
2. F 意为Flip。将平板沿着给定的对称轴翻转,原来处于位置1 的珠子不动,位置2 上的珠子与位置N 上的珠子互换,位置3 上的珠子与位置N-1 上的珠子互换,依次类推。
3.S i j(1≤I,j≤N) 意为Swap i , j。将位置i 上的珠子与位置j 上的珠子互换。
4.P I j x(1≤I,j≤N,x≤c) 意为Paint i , j , x。将位置i 沿顺时针方向到位置j 的一段染为颜色x。
5.C 意为Count。查询当前的项链由多少个“部分”组成,我们称项链中颜色相同的一段为一个“部分”。
6.CS i j(1≤I,j≤N) 意为CountSegment i , j。查询从位置i沿顺时针方向到位置j 的一段中有多少个部分组成。
Input
输入文件第一行包含两个整数N, c,分别表示项链包含的珠子数目以及颜色数目。
第二行包含N 个整数,x1, x2…, xn,表示从位置1 到位置N 的珠子的颜色,1 ≤ xi ≤ c。
第三行包含一个整数Q,表示命令数目。
接下来的Q 行每行一条命令,如上文所述。
Output
对于每一个C 和CS 命令,应输出一个整数代表相应的答案。
Sample Input
5 31 2 3 2 14CR 2P 5 5 2CS 4 1
Sample Output
41
Data Constraint
Hint
【数据规模和约定】
对于60%的数据,N ≤ 1 000,Q ≤ 1 000;
对于100%的数据,N ≤ 500 000,Q ≤ 500 000,c ≤ 1 000。
分析
说实话一开始根本没想线段树,考虑到前面各种奇怪的操作,我想到的是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\n",z=z-((z!=1)?(t[rt].l==t[rt].r):0)); } else if (x<=y) printf("%d\n",z=Query(rt,1,n,x,y)); else { int z=Query(rt,1,n,x,n)+Query(rt,1,n,1,y); printf("%d\n",z=z-((z!=1)?(t[rt].l==t[rt].r):0)); } } } } }
原文地址:https://www.cnblogs.com/mastervan/p/11145014.html