题意
- 题目链接: http://poj.org/problem?id=2777
- 题意:有一个长板子,多次操作,有两种操作,第一种是给从a到b那段染一种颜色c,另一种是询问a到b有多少种不同的颜色。输入别用cin
思路
-
结构体node存放左右端点l, r,和染色id(num表示);num > 0; 表示这一部分[l, r]染成num色, num = 11, 表示[l, r]有多种颜色
-
built()老规矩建树,初始颜色都为1; update(),不用更新到最底层,更新[l, r]的区间颜色,这里有一个lazy思想,从根节点更新区间,如果这个区间染色后将会有多种颜色就往子节点跟新,两个左右子节点继承父节点的颜色, 父节点的颜色为-1; query():由于所有区间一种颜色num大于0, 多种颜色num小于0, 所以判断tree【node】.num,为-1,就继续查询,不为-1,就直接标记。
代码
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 100010;
bool vis[35];
struct{
int l, r;
int num;
}tree[maxn << 2];
void built(int s, int e, int node){
tree[node].l = s;
tree[node].r = e;
tree[node].num = 1;
int mid = (s + e) >> 1;
if(s == e){
return ;
}
built(s, mid, node << 1);
built(mid + 1, e, node << 1 | 1);
}
void down(int node){
if(tree[node].num != -1){//如果[l,r],一种颜色,更新后出现两种颜色下传父节点颜色给子节点
tree[node << 1].num = tree[node].num;
tree[node << 1 | 1].num = tree[node].num;
tree[node].num = -1;
}
}
void update(int L, int R, int node, int num){
if(tree[node].l >= L && tree[node].r <= R){
tree[node].num = num;
return ;
}
else{
if(tree[node].num != num) down(node);
int mid = (tree[node].l + tree[node].r) >> 1;
if(mid < L) update(L, R, node << 1 | 1, num);
else if(mid >= R) update(L, R, node << 1, num);
else{
update(mid | 1, R, node << 1 | 1, num);
update(L, mid, node << 1, num);
}
}
}
int query(int L, int R, int node){
if(tree[node].num != -1){
vis[tree[node].num] = true;//用一个数组来标记
return 1;
}
int mid = (tree[node].l + tree[node].r) >> 1;
if(L > mid){
query(L, R, node << 1 | 1);
}else if(R <= mid){
query(L, R, node << 1);
}else{
query(L, mid, node << 1);
query(mid + 1, R, node << 1 | 1);
}
}
int main(){
int n, t, o;
char ctr;
int l, r, num;
while(cin >> n >> t >> o){
built(1, n, 1);
while(o --){//线段树切忌用cin scanf才不会超时
cin >> ctr;
if(ctr == 'C'){
scanf("%d%d%d", &l, &r, &num);
if(l > r) update(r, l, 1, num);
else update(l, r, 1, num);
}else{
scanf("%d%d", &l, &r);
memset(vis, false, sizeof(vis));
if(l > r) query(r, l, 1);
else query(l ,r, 1);
int ans = 0;
for(int i = 1; i <= t; i++){
ans += vis[i];
}
cout << ans << endl;
}
}
}
return 0;
}