1493: [NOI2007]项链工厂
Time Limit: 30 Sec Memory Limit: 64 MB
Submit: 1712 Solved: 723
[Submit][Status][Discuss]
Description
T公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖、款式多样、价格适中,广受青年人的喜爱。
最近T公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链。该项链自助生产系
统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的
项链。该系统的硬件系统已经完成,而软件系统尚未开发,T公司的人找到了正在参加全国信息学竞赛的你,你能
帮助T公司编写一个软件模拟系统吗?一条项链包含 N 个珠子,每个珠子的颜色是 1,2,…,c 中的一种。项链
被固定在一个平板上,平板的某个位置被标记位置 1 ,按顺时针方向其他位置被记为 2,3,…,N。
你将要编写的软件系统应支持如下命令:
Input
输入文件第一行包含两个整数 N,c ,分别表示项链包含的珠子数目以及颜色数目。
第二行包含 N 个整数,x1,x2,…,xn ,表示从位置 1 到位置 N 的珠子的颜色,1≤xi≤c 。
第三行包含一个整数 Q ,表示命令数目。接下来的 Q 行每行一条命令,如上文所述。N≤500000 ,Q≤500000,c≤1000
Output
对于每一个 C 和 CS 命令,应输出一个整数代表相应的答案。
Sample Input
5 3
1 2 3 2 1
4
C
R 2
P 5 5 2
CS 4 1
Sample Output
4
1
HINT
注意旋转命令旋转“珠子”但不改变“位置”的编号,而反转命令始终以位置 1 为对称轴。例如当 N=10 时,项
链上的位置编号如图1:
但注意此时项链上的位置编号仍然如图1所示,于是翻转的对称轴不变。因而再执行一次“F”命令时,项链的颜色
如图4所示。
2. 关于CountSegment命令CS命令表示查询一个“线段”中有多少个“部分”。尤其注意当查询的长度
等于 N 时,我们仍然将查询部分作为“线段”理解。例如在图4所示的情况中,执行“CS 1 10”命令,查询从位
置 1 开始到位置 10 结束的这个长度为 10 的线段中有多少个“部分”,于是得到返回值 3 。与之形成对照的是
,若执行“C”命令,返回值则为 2
Source
可以注意到不管项链怎么变,它上面颜色的相对位置不变,所以只要开全局变量记录变化就好
维护线段树,常规区间操作,注意合并
全局变量维护位置看 http://blog.csdn.net/Regina8023/article/details/41697557
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define ls u<<1 #define rs ls|1 #define ll long long #define N 500050 using namespace std; int n,m,rev,mov,a[N]; struct node{ int lz,sum,l,r; node(){lz=sum=l=r=0;}; }t[N<<2]; void get(int &x,int &y){ if(rev){x=n-x+2;y=n-y+2;} x-=mov;y-=mov; if(x<=0)x+=n;if(x>n)x-=n; if(y<=0)y+=n;if(y>n)y-=n; } node merge(node x,node y){ node ret; ret.sum=x.sum+y.sum; if(x.r==y.l)ret.sum--; ret.l=x.l;ret.r=y.r; if(!ret.l)ret.l=y.l; if(!ret.r)ret.r=x.r; return ret; } void pushdown(int u){ if(!t[u].lz)return; int x=t[u].lz; t[ls].lz=t[rs].lz=x; t[ls].l=t[ls].r=x; t[rs].l=t[rs].r=x; t[ls].sum=t[rs].sum=1; t[u].lz=0; } void build(int u,int l,int r){ if(l==r){ t[u].l=t[u].r=a[l]; t[u].sum=1;return; } int mid=l+r>>1; build(ls,l,mid); build(rs,mid+1,r); t[u]=merge(t[ls],t[rs]); } void update(int u,int L,int R,int l,int r,int val){ if(l<=L&&R<=r){ t[u].l=t[u].r=t[u].lz=val; t[u].sum=1;return; } pushdown(u); int mid=L+R>>1; if(l<=mid)update(ls,L,mid,l,r,val); if(r>mid)update(rs,mid+1,R,l,r,val); t[u]=merge(t[ls],t[rs]); } node query(int u,int L,int R,int l,int r){ if(l<=L&&R<=r)return t[u]; pushdown(u);int mid=L+R>>1; node t1,t2; if(l<=mid)t1=query(ls,L,mid,l,r); if(r>mid)t2=query(rs,mid+1,R,l,r); return merge(t1,t2); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); char s[5];int x=0,y=0,z=0; scanf("%d",&m); while(m--){ scanf("%s",s); if(s[0]==‘R‘){ scanf("%d",&x); if(rev)mov-=x; else mov+=x; if(mov<0)mov+=n; if(mov>=n)mov-=n; } else if(s[0]==‘F‘)rev^=1; else if(s[0]==‘S‘){ scanf("%d%d",&x,&y); get(x,y);if(rev)swap(x,y); node t1=query(1,1,n,x,x); node t2=query(1,1,n,y,y); update(1,1,n,x,x,t2.l); update(1,1,n,y,y,t1.l); } else if(s[0]==‘P‘){ scanf("%d%d%d",&x,&y,&z); get(x,y);if(rev)swap(x,y); if(x<=y)update(1,1,n,x,y,z); else{ update(1,1,n,x,n,z); update(1,1,n,1,y,z); } } else if(s[0]==‘C‘&&s[1]==‘S‘){ scanf("%d%d",&x,&y); get(x,y);if(rev)swap(x,y); if(x<=y)printf("%d\n",query(1,1,n,x,y).sum); else{ node t1=query(1,1,n,x,n); node t2=query(1,1,n,1,y); node t3=merge(t1,t2); printf("%d\n",t3.sum); } } else{ int ans=t[1].sum; if(t[1].l==t[1].r&&ans>1)ans--; printf("%d\n",ans); } // printf("%d %d %d %d\n",mov,rev,x,y); } return 0; }