POJ 2777 Count Color (线段树成段更新+二进制思维)

题目链接:http://poj.org/problem?id=2777

题意是有L个单位长的画板,T种颜色,O个操作。画板初始化为颜色1。操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的颜色有几种。

很明显的线段树成段更新,但是查询却不好弄。经过提醒,发现颜色的种类最多不超过30种,所以我们用二进制的思维解决这个问题,颜色1可以用二进制的1表示,同理,颜色2用二进制的10表示,3用100,...。假设有一个区间有颜色2和颜色3,那么区间的值为二进制的110(十进制为6)。那我们就把一个区间的颜色种类表示为(左孩子的值‘|’右孩子的值)。

然后就是一个线段树的成段更新。

有个坑点是这个题目的l可能比r大...

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = ;
struct segtree {
int l , r , val , lazy;
}T[MAXN << ];
//获取颜色的种类
int get(int n) {
int cont = ;
while(n) {
if(n & )
cont++;
n >>= ;
}
return cont;
} void init(int p , int l , int r) {
int mid = (l + r) >> ;
T[p].l = l , T[p].r = r , T[p].lazy = ;
if(l == r) {
T[p].val = ;
return ;
}
init(p << , l , mid);
init((p << )| , mid + , r);
T[p].val = (T[p << ].val | T[(p << )|].val);
} void updata(int p , int l , int r , int val) {
int mid = (T[p].l + T[p].r) >> ;
if(l == T[p].l && T[p].r == r) {
T[p].val = val;
T[p].lazy = val;
return ;
}
if(T[p].lazy) {
T[p << ].val = T[(p << )|].val = T[p].lazy;
T[p << ].lazy = T[(p << )|].lazy = T[p].lazy;
T[p].lazy = ;
}
if(r <= mid) {
updata(p << , l , r , val);
}
else if(l > mid) {
updata((p << )| , l , r , val);
}
else {
updata(p << , l , mid , val);
updata((p << )| , mid + , r , val);
}
T[p].val = (T[p << ].val | T[(p << )|].val);
}
//返回颜色种类的二进制对应的十进制的值
int query(int p , int l , int r) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == l && T[p].r == r) {
return T[p].val;
}
if(T[p].lazy) {
T[p << ].val = T[(p << )|].val = T[p].lazy;
T[p << ].lazy = T[(p << )|].lazy = T[p].lazy;
T[p].lazy = ;
}
if(r <= mid) {
return query(p << , l , r);
}
else if(l > mid) {
return query((p << )| , l , r);
}
else {
return query(p << , l , mid) | query((p << )| , mid + , r);
}
} int main()
{
int L , t , n , l , r , c;
char str[];
while(~scanf("%d %d %d" , &L , &t , &n)) {
init( , , L);
while(n--) {
scanf("%s" , str);
if(str[] == 'C') {
scanf("%d %d %d" , &l , &r , &c);
int temp = l + r;
l = min(l , r);
r = temp - l;
updata( , l , r , ( << (c - )));
}
else {
scanf("%d %d" , &l , &r);
int temp = l + r;
l = min(l , r);
r = temp - l;
int res = get(query( , l , r));
printf("%d\n" , res);
}
}
}
}
上一篇:Java RMI(远程方法调用) 实例与分析


下一篇:visual studio 和 sql server 的激活密钥序列号