题目描述
项链工厂 问题描述 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.