您的位置:首页 > 其它

POJ 2777 Count Color 线段树 + lazy标记

2013-10-12 22:43 417 查看
/**
*      线段树 + lazy标记
*     维护区间所含颜色种数,依题种数小于30,很容易想到用位压缩记录状态,
*   在更新的时候用 按位与(a | b) 就能合并两个区间所有的颜色,询问的时候返回
*   区间所记录的颜色种数(一个int型的数),返回后,再计算各位上含1的个数即为种数。
*   规定第i种颜色为(1<<i)
*     其次是更新,用个lazy标记表示是否整个区间都染成同一种颜色即可。
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#define DEBUG 0
#define INF 0x1fffffff
#define MAXN 100005
#define OUTSTARS  printf("*****************************\n");

typedef long long LL;
using namespace std;

struct Seg
{
    int l, r, c;
    int set;
} tree[MAXN << 4];
int l, t, o;

void build(int l, int r, int id)
{
    tree[id].l = l;  tree[id].r = r;
    tree[id].set = 1;
    tree[id].c = 1<<1;
    if(l == r) return ;
    int mid = (l + r) / 2;
    build(l, mid, id << 1);
    build(mid + 1, r, id << 1 | 1);
}

void push_down(int id)
{
    if(tree[id].set) {
        tree[id<<1].set = tree[id].set;
        tree[id<<1].c = tree[id].c;
        tree[id<<1|1].set = tree[id].set;
        tree[id<<1|1].c = tree[id].c;
        tree[id].set = 0;
    }
}

int query(int L, int R, int id)
{
    int ll = 0, rr = 0;
    push_down(id);
    if(L <= tree[id].l && R >= tree[id].r) {
        return tree[id].c;
    }
    int mid = (tree[id].l + tree[id].r) / 2;
    if(L <= mid)
       ll = query(L, R, id << 1);
    if(R > mid)
       rr = query(L, R, id << 1 | 1);
    return ll | rr;
}

void update(int L, int R, int c, int id)
{
    int mid = (tree[id].l + tree[id].r) / 2;
    push_down(id);
    if(L <= tree[id].l && R >= tree[id].r)
    {
        tree[id].set = 1;
        tree[id].c = 1 << c;
    }
    else
    {
        if(L <= mid) update(L, R, c, id << 1);
        if(R > mid)  update(L, R, c, id << 1 | 1);
        tree[id].c = tree[id<<1].c | tree[id<<1|1].c;
    }
}

/** 计算颜色种数,即计算一个数中的各位上1的总数 */
int cal_bit(int x)
{
    int ret = 0;
    for(; x; x >>= 1)  if(x & 1) ret ++;
    return ret;
}

int main()
{
    while(scanf("%d%d%d", &l, &t, &o) != EOF)
    {
        build(1, l, 1);
        for(int i = 1; i <= o; i ++)
        {
            getchar();
            char ch = getchar();
            if(ch == 'C')
            {
                int L, R, c;
                scanf("%d%d%d", &L, &R, &c);
                if(L > R) swap(L, R);
                update(L, R, c, 1);
            }
            else if(ch == 'P')
            {
                int L, R;
                scanf("%d%d", &L, &R);
                if(L > R) swap(L, R);
                printf("%d\n", cal_bit(query(L, R, 1)));
            }
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: