数颜色
http://poj.org/problem?id=2777
http://cdqz.openjudge.cn/noip/1032/
时间限制: 2000ms 内存限制: 512000kB
描述
给你一个长为L的木板,L是一个整数,我们把它分成L格1、2…,L,我们现在对在这块木板上涂色,每个小格只能涂一种颜色。
现在有两种操作
1:”C A B C”,把在[A,B]之间全部涂成颜色C,原先的颜色会被覆盖。
2:”P A B”,输出[A,B]内不同的颜色数。
颜色用数字表示,初始时整块木板涂为颜色1
输入
每个文件一组测试数据,
第一行为”L T O”
L: (1 <= L <= 100000) 表示木板长度
T:(1 <= T <= 30) 表示所使用的颜色总数,颜色为[1,T]
O:(1 <= O <= 100000) 表示操作数
接下来有O行,每行包括"C A B C" 或者 "P A B" (A可能大于B,此时区间为[B,A])。
1 <= A,B <= L
输出
对于每个P操作输出一行结果。
样例输入
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
样例输出
2
1
题解:
看到这道题的第一反应:线段树。
具体实现只是把头两天线段树的模板中记录最大值改为记录颜色总数,而由于一个区间对于一种颜色只有涂或不涂两种状态,所以想到位压缩。依旧记一个标记,表示该区间都被改为某种颜色,然后递归的过程中将每个节点记录的信息更改。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 type 2 segtree=record 3 ls,rs,d,f:longint; 4 end; 5 var 6 a:array[1..500000]of segtree; 7 l,t,o,m,n,x,y:longint; 8 c:char; 9 function change_color(q:longint):longint; 10 begin 11 change_color:=1 shl (q-1); 12 end; 13 procedure push(rt:longint); 14 begin 15 if a[rt].f<>0 then begin 16 a[rt].d:=change_color(a[rt].f); 17 if a[rt].ls<>a[rt].rs then begin 18 a[rt shl 1].f:=a[rt].f; 19 a[(rt shl 1)or 1].f:=a[rt].f; 20 end; 21 a[rt].f:=0; 22 end; 23 end; 24 procedure update(rt:longint); 25 begin 26 push(rt shl 1); 27 push((rt shl 1)or 1); 28 a[rt].d:=a[rt shl 1].d or a[(rt shl 1)or 1].d; 29 end; 30 procedure build(rt,left,right:longint); 31 var 32 p:longint; 33 begin 34 a[rt].ls:=left; 35 a[rt].rs:=right; 36 if left=right then 37 a[rt].d:=1 else begin 38 p:=(left+right)shr 1; 39 build(rt shl 1,left,p); 40 build((rt shl 1)or 1,p+1,right); 41 update(rt); 42 end; 43 end; 44 function sum_root(p,rt:longint):longint; 45 begin 46 push(rt); 47 sum_root:=p or a[rt].d; 48 end; 49 function sum_color(p,q:longint):longint; 50 begin 51 sum_color:=p or q; 52 end; 53 function count_color(p:longint):longint; 54 begin 55 count_color:=0; 56 repeat 57 if (p mod 2<>0) then inc(count_color); 58 p:=p shr 1; 59 until p=0; 60 end; 61 procedure change(rt,left,right:longint); 62 var 63 p:longint; 64 begin 65 if (a[rt].ls>=left)and(a[rt].rs<=right) then begin 66 a[rt].d:=change_color(n); 67 a[rt].f:=n end else begin 68 push(rt); 69 p:=(a[rt].ls+a[rt].rs)shr 1; 70 if p>=left then change(rt shl 1,left,right); 71 if p<right then change((rt shl 1)or 1,left,right); 72 update(rt); 73 end; 74 end; 75 function find(rt,left,right:longint):longint; 76 var 77 p:longint; 78 begin 79 find:=0; 80 if (a[rt].ls>=left)and(a[rt].rs<=right) then 81 inc(find,sum_root(find,rt)) else begin 82 push(rt); 83 p:=(a[rt].ls+a[rt].rs)shr 1; 84 if p>=left then find:=sum_color(find,find(rt shl 1,left,right)); 85 if p<right then find:=sum_color(find,find((rt shl 1)or 1,left,right)); 86 update(rt); 87 end; 88 end; 89 begin 90 read(l,t); 91 readln(o); 92 build(1,1,l); 93 for m:=1 to o do begin 94 read(c); 95 case c of 96 'C': begin 97 read(x,y); 98 readln(n); 99 if x>y then change(1,y,x) else change(1,x,y); 100 end; 101 'P': begin 102 read(x); 103 readln(y); 104 if x>y then writeln(count_color(find(1,y,x))) 105 else writeln(count_color(find(1,x,y))); 106 end; 107 end; 108 end; 109 end.