【NOI2007】 项链工厂

题目描述
项链工厂
问题描述
T 公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖、款式
多样、价格适中,广受青年人的喜爱。最近 T 公司打算推出一款项链自助生产
系统,使用该系统顾客可以自行设计心目中的美丽项链。
该项链自助生产系统包括硬件系统与软件系统,软件系统与用户进行交互并
控制硬件系统,硬件系统接受软件系统的命令生产指定的项链。该系统的硬件系
统已经完成,而软件系统尚未开发,T 公司的人找到了正在参加全国信息学竞赛
的你,你能帮助 T 公司编写一个软件模拟系统吗?
一条项链包含 N 个珠子,每个珠子的颜色是 1, 2, ..., c 中的一种。项链被固
定在一个平板上,平板的某个位置被标记位置 1,按顺时针方向其他位置被记为2,3,...,N。

你将要编写的软件系统应支持如下命令:

命令
参数限制
内容

Rk  
0<k<N
意为 Rotate k。将项链在平板上顺时针旋转 k 个位置, 即原来处于位置 1 的珠子将转至位置 k+1,处于位置 2 的珠子将转至位置 k+2,依次类推。

F
意为 Flip。将平板沿着给定的对称轴翻转,原来处于位置 1 的珠子不动,位置2 上的珠子与位置 N 上的珠子互换,位置 3 上的珠子与位置 N-1 上的珠子互
换,依次类推。

S i j  1≤i , j≤N
意为 Swap i , j。将位置 i 上的珠子与位置 j 上的珠子互换。

P i j x 1≤i , j≤N, x≤c
意为 Paint i , j , x。将位置 i 沿顺时针方向到位置 j 的一段染为颜色 x。

C
意为 Count。查询当前的项链由多少个“部分”组成,我们称项链中颜色相同的一段为一个“部分”。

CS i j
1≤i , j≤N
意为 CountSegment i , j。查询从位置 i沿顺时针方向到位置 j 的一段中有多少个部分组成。

输入文件
输入文件第一行包含两个整数 N, c,分别表示项链包含的珠子数目以及颜色
数目。
第二行包含 N 个整数, 1, x2..., xn,
表示从位置 1 到位置 N 的珠子的颜色,
1 ≤ xi ≤ c。
第三行包含一个整数 Q,表示命令数目。
接下来的 Q 行每行一条命令,如上文所述。
输出文件
对于每一个 C 和 CS 命令,应输出一个整数代表相应的答案。
输入样例
53
12321
4
C
R2
P552
CS 4 1
输出样例
4
1
评分方法
本题没有部分分,你的程序的输出只有和标准答案完全一致才能获得满分,
否则不得分。
数据规模和约定
对于 60%的数据,N ≤ 1 000,Q ≤ 1 000;
对于 100%的数据,N ≤ 500 000,Q ≤ 500 000,c ≤ 1 000

 

 

题解

 

解法1:线性表
  1 (*
  2     Problem:    NOI2007 项链工厂
  3     Author:        Chen Yang
  4     Time:        2012.5.30 9:00 pm
  5     State:        60分
  6     Memo:        坐标变换、线性表
  7 *)
  8 program necklace;
  9 uses math;
 10 const maxn=500100;
 11 var
 12   n,col,i,j,one,s,q,k,t,k1:longint;
 13   p:char;
 14   c:array[0..maxn] of longint;
 15 //=======================
 16 begin
 17   assign(input,'necklace.in'); reset(input);
 18   assign(output,'necklace.out'); rewrite(output);
 19   read(n,col);
 20   for i:=1 to n do read(c[i]); c[0]:=c[n];
 21   for i:=n+1 to n << 1 do c[i]:=c[i-n];
 22   one:=1; s:=1;
 23   readln(q);
 24   for i:=1 to q do
 25   begin
 26     read(p);
 27     //writeln(P);
 28     case p of
 29     'R':begin
 30           readln(k);
 31           one:=(one+n-s*k) mod (n<<1);
 32           if (s=-1)and(one<=n) then inc(one,n) else
 33           if (s=1)and(one>n) then dec(one,n);
 34         end;
 35     'F':begin
 36           s:=-s; readln;
 37           if (s=-1)and(one<=n) then inc(one,n) else
 38           if (s=1)and(one>n) then dec(one,n);
 39         end;
 40     'S':begin
 41           readln(j,k); j:=one+j*s-s; k:=one+k*s-s; //writeln(k,' ',j);
 42           t:=c[j]; c[j]:=c[k]; c[k]:=t;
 43           c[(j+n) mod (n<<1)]:=c[j]; c[(k+n) mod (n<<1)]:=c[k];
 44           //writeln((j+n) mod (n<<1),' ',(k+n) mod (n<<1));
 45           c[n<<1]:=c[0];
 46         end;
 47     'P':begin
 48           readln(j,k,t); j:=(one+j*s-s) mod n; k:=(one+k*s-s) mod n;
 49           //writeln(j,' ',k);
 50           {for k1:=min(k,j) to max(j,k) do
 51           begin
 52             c[k1]:=t; c[(k1+n) mod (n<<1)]:=t;
 53           end;}
 54           if s=1 then
 55             begin
 56               if k<j then inc(k,n);
 57               for k1:=j to k do
 58               begin
 59                 c[k1]:=t; c[(k1+n) mod (n<<1)]:=t;
 60               end;
 61             end else
 62             begin
 63               if k>j then inc(j,n);
 64               for k1:=k to j do
 65               begin
 66                 c[k1]:=t; c[(k1+n) mod (n<<1)]:=t;
 67               end;
 68             end;
 69           c[n<<1]:=c[0];
 70         end;
 71     'C':begin
 72           read(p);
 73           if p='S' then
 74           begin
 75             readln(j,k); j:=(one+j*s-s) mod n; k:=(one+k*s-s) mod n; t:=1;
 76             //writeln(j,' ',k);
 77             if s=1 then
 78             begin
 79               if k<j then inc(k,n);
 80               for k1:=j+1 to k do
 81               if c[k1]<>c[k1-1] then inc(t);
 82             end else
 83             begin
 84               if k>j then inc(j,n);
 85               for k1:=k+1 to j do
 86               if c[k1]<>c[k1-1] then inc(t);
 87             end;
 88             writeln(t);
 89           end else
 90           begin
 91             t:=0;
 92             for k1:=1 to n do
 93             if c[k1]<>c[k1-1] then inc(t);
 94             if t=0 then inc(t);
 95             writeln(t);
 96           end;
 97         end;
 98     end;
 99     //for j:=0 to 2*n do write(c[j],' '); writeln;
100     //writeln(one,' ',s);
101   end;
102   close(input); close(output);
103 end.

 

解法2:线段树
  1 (*
  2     Problem:    NOI2007 项链工厂
  3     Author:        Chen Yang
  4     Time:        2012.5.29 3:50 pm
  5     State:        Solved
  6     Memo:        线段树、坐标变换
  7     Lesson:        To try
  8 *)
  9 program necklace;
 10 uses math;
 11 const maxn=500100;
 12       maxm=2000000;
 13 type
 14   lt=record
 15     l,r,sum,rc,lc:longint;
 16     lazy:boolean;
 17   end;
 18 var
 19   n,col,i,j,one,fs,q,k,t,k1:longint;
 20   t1,t2:lt;
 21   p:char;
 22   c:array[0..maxn] of longint;
 23   s:array[0..maxm] of lt;
 24 //=======================
 25 procedure maintain(var a,b,c:lt);    inline;
 26 begin
 27   a.sum:=b.sum+c.sum;
 28   if b.rc=c.lc then dec(a.sum);
 29   a.lc:=b.lc; a.rc:=c.rc;
 30   if a.sum=1 then a.lazy:=true else a.lazy:=false;
 31 end;
 32 //=======================
 33 procedure pushlazy(x:longint);       inline;
 34 var
 35   ls,rs:longint;
 36 begin
 37   ls:=x shl 1; rs:=x shl 1+1;
 38   s[ls].lazy:=true;  s[ls].sum:=1;
 39   s[ls].lc:=s[x].lc; s[ls].rc:=s[x].rc;
 40   s[rs].lazy:=true;  s[rs].sum:=1;
 41   s[rs].lc:=s[x].lc; s[rs].rc:=s[x].rc;
 42 end;
 43 //=======================
 44 procedure built(x,l,r:longint);
 45 var
 46   m:longint;
 47 begin
 48   s[x].l:=l; s[x].r:=r;
 49   if l=r then
 50   begin
 51     s[x].lc:=c[l]; s[x].rc:=c[r];
 52     s[x].sum:=1; s[x].lazy:=true;
 53     exit;
 54   end;
 55   s[x].sum:=0; s[x].lazy:=false;
 56   s[x].lc:=0; s[x].rc:=0;
 57   m:=(l+r)>>1;
 58   built(x shl 1,l,m);
 59   built(x shl 1+1,m+1,r);
 60   maintain(s[x],s[x shl 1],s[x shl 1+1]);
 61 end;
 62 //=======================
 63 function find_col(x,p:longint):longint;
 64 var
 65   m:longint;
 66 begin
 67   if (s[x].l<=p)and(p<=s[x].r)and s[x].lazy then exit(s[x].lc);
 68   if s[x].lazy then pushlazy(x);
 69   m:=(s[x].l+s[x].r)>>1;
 70   if p<=m then exit(find_col(x shl 1,p)) else
 71   if p>m then exit(find_col(x shl 1+1,p));
 72 end;
 73 //=======================
 74 function find(x,l,r:longint):lt;
 75 var
 76   m:longint;
 77   t1,t2,t:lt;
 78 begin
 79   if (l<=s[x].l)and(s[x].r<=r)and s[x].lazy then exit(s[x]);
 80   if s[x].lazy then pushlazy(x);
 81   m:=(s[x].l+s[x].r)>>1;
 82   if r<=m then exit(find(x shl 1,l,r)) else
 83   if l>m then exit(find(x shl 1+1,l,r)) else
 84   begin
 85     t1:=find(x shl 1,l,r); t2:=find(x shl 1+1,l,r);
 86     maintain(t,t1,t2);
 87   end;
 88   exit(t);
 89 end;
 90 //=======================
 91 procedure change(x,l,r,c:longint);
 92 var
 93   m:longint;
 94 begin
 95   if (l<=s[x].l)and(s[x].r<=r) then
 96   begin
 97     s[x].lazy:=true; s[x].sum:=1;
 98     s[x].lc:=c; s[x].rc:=c;
 99     exit;
100   end;
101   if s[x].lazy then pushlazy(x);
102   m:=(s[x].l+s[x].r)>>1;
103   if r<=m then change(x shl 1,l,r,c) else
104   if l>m then change(x shl 1+1,l,r,c) else
105   begin
106     change(x shl 1,l,r,c); change(x shl 1+1,l,r,c);
107   end;
108   maintain(s[x],s[x shl 1],s[x shl 1+1]);
109 end;
110 //=======================
111 begin
112   assign(input,'necklace.in'); reset(input);
113   assign(output,'necklace.out'); rewrite(output);
114   read(n,col);
115   for i:=1 to n do read(c[i]); c[0]:=c[n];
116   built(1,0,n-1);
117   one:=1; fs:=1;
118   readln(q);
119   for i:=1 to q do
120   begin
121     read(p);
122     case p of
123     'R':begin
124           readln(k);
125           one:=(one+n-fs*k) mod n;
126         end;
127     'F':begin
128           fs:=-fs; readln;
129         end;
130     'S':begin
131           readln(j,k); j:=(one+j*fs-fs) mod n; k:=(one+k*fs-fs) mod n;
132           if j=k then continue;
133           t:=find_col(1,k); k1:=find_col(1,j);
134           if t=k1 then continue;
135           change(1,j,j,t); change(1,k,k,k1);
136         end;
137     'P':begin
138           readln(j,k,t); j:=(one+j*fs-fs) mod n; k:=(one+k*fs-fs) mod n;
139           if fs=1 then
140             begin
141               if k>=j then change(1,j,k,t) else
142               begin
143                 change(1,j,n-1,t); change(1,0,k,t);
144               end;
145             end else
146             begin
147               if j>=k then change(1,k,j,t) else
148               begin
149                 change(1,k,n-1,t); change(1,0,j,t);
150               end;
151             end;
152         end;
153     'C':begin
154           read(p);
155           if p='S' then
156           begin
157             readln(j,k); j:=(one+j*fs-fs) mod n; k:=(one+k*fs-fs) mod n; t:=1;
158             if fs=1 then
159             begin
160               if k>=j then t:=find(1,j,k).sum
161               else begin
162                 t1:=find(1,j,n-1); t2:=find(1,0,k);
163                 t:=t1.sum+t2.sum;
164                 if t1.rc=t2.lc then dec(t);
165               end;
166             end else
167             begin
168               if j>=k then t:=find(1,k,j).sum
169               else begin
170                 t1:=find(1,k,n-1); t2:=find(1,0,j);
171                 t:=t1.sum+t2.sum;
172                 if t1.rc=t2.lc then dec(t);
173               end;
174             end;
175             writeln(t);
176           end else
177           begin
178             t:=find(1,0,n-1).sum;
179             if (t>1)and(s[1].lc=s[1].rc) then dec(t);
180             writeln(t);
181           end;
182         end;
183     end;
184   end;
185   close(input); close(output);
186 end.

转载于:https://www.cnblogs.com/datam-cy/archive/2012/05/30/NOI2007-DAY2-XLGC.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值