poj 2777 Count Color(线段树(有点意思))

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

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

这题区间更新很简单但是查询会发现挺麻烦的,主要是不知道怎么判断一个区间到底有几个不同的数。

由于这道题的T比较小才30,1<<30不超过int型于是可以考虑用状态来表示,1表示color1,10表示color2,100表示color3,以此类推。

然后区间更新时注意父节点的变化T[p].sum=(T[p<<1].sum | T[(p<< 1)|1].sum)两种状态相加来表示最后只要看一下着个区间有几个

1就行了。

 

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int inf = 1 << 30;
const int M = 1e5 + 10;
struct TnT {
    int l , r , sum , add;
}T[M << 2];
void build(int l , int r , int p) {
    int mid = (l + r) >> 1;
    T[p].l = l , T[p].r = r , T[p].add = 0;
    if(T[p].l == T[p].r) {
        T[p].sum = 1;
        return ;
    }
    build(l , mid , p << 1);
    build(mid + 1 , r , (p << 1) | 1);
    T[p].sum = (T[p << 1].sum | T[(p << 1) | 1].sum);
}
int Get(int x) {
    int temp = 1;
    for(int i = 1 ; i < x ; i++) {
        temp <<= 1;
    }
    return temp;
}
void pushdown(int p) {
    if(T[p].add) {
        T[p << 1].sum = T[p].add;
        T[(p << 1) | 1].sum = T[p].add;
        T[p << 1].add = T[p].add;
        T[(p << 1) | 1].add = T[p].add;
        T[p].add = 0;
    }
}
void updata(int l , int r , int ad , int p) {
    int mid = (T[p].l + T[p].r) >> 1;
    if(T[p].l == l && T[p].r == r) {
        T[p].add = ad;
        T[p].sum = ad;
        return ;
    }
    pushdown(p);
    if(mid >= r) {
        updata(l , r , ad , p << 1);
    }
    else if(mid < l) {
        updata(l , r , ad , (p << 1) | 1);
    }
    else {
        updata(l , mid , ad , p << 1);
        updata(mid + 1 , r , ad , (p << 1) | 1);
    }
    T[p].sum = (T[p << 1].sum | T[(p << 1) | 1].sum);
}
int query(int l , int r , int p) {
    int mid = (T[p].l + T[p].r) >> 1;
    if(T[p].l == l && T[p].r == r) {
        return T[p].sum;
    }
    pushdown(p);
    if(mid >= r) {
        return query(l , r , p << 1);
    }
    else if(mid < l) {
        return query(l , r , (p << 1) | 1);
    }
    else {
        return (query(l , mid , p << 1) | query(mid + 1 , r , (p << 1) | 1));
    }
}
int Gets(int x) {
    int temp = 0;
    while(x) {
        if(x & 1) {
            temp++;
        }
        x >>= 1;
    }
    return temp;
}
int main() {
    int l , t , o;
    scanf("%d%d%d" , &l , &t , &o);
    char cp[2];
    build(1 , l , 1);
    for(int i = 1 ; i <= o ; i++) {
        int a , b , c;
        scanf("%s" , cp);
        if(cp[0] == 'C') {
            scanf("%d%d%d" , &a , &b , &c);
            if(a > b) {
                int gl = a;
                a = b;
                b = gl;
            }
            int gg = Get(c);
            updata(a , b , gg , 1);
        }
        if(cp[0] == 'P') {
            scanf("%d%d" , &a , &b);
            if(a > b) {
                int gl = a;
                a = b;
                b = gl;
            }
            int gg = query(a , b , 1);
            int counts = Gets(gg);
            printf("%d\n" , counts);
        }
    }
    return 0;
}
posted @ 2016-12-04 21:03  Gealo  阅读(208)  评论(0编辑  收藏  举报