数颜色

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

题解:
看到这道题的第一反应:线段树。
具体实现只是把头两天线段树的模板中记录最大值改为记录颜色总数,而由于一个区间对于一种颜色只有涂或不涂两种状态,所以想到位压缩。依旧记一个标记,表示该区间都被改为某种颜色,然后递归的过程中将每个节点记录的信息更改。

代码如下:

View Code
  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.
posted @ 2012-07-12 15:51  wangziyun  阅读(183)  评论(0编辑  收藏  举报
神奇的东西