poj2777 Count Color(线段树+状压)

来源:互联网 发布:大疆精灵 知乎 编辑:程序博客网 时间:2024/06/02 22:01

题目大意

描述

给一块长为L的长板染色,有两种操作:
1.“C A B C”用颜色C将板从A段着色到B段。
2.“P A B”输出A段和B段(包括A和B)之间的不同颜色的数量。

输入

第一行输入包含L(1 <= L <= 100000),T(1 <= T <= 30)和O(1 <= 0 <= 100000)。这里O表示操作次数。后O行,每行包含“C A B C”或“P A B”(这里A,B,C是整数,并且A可以大于B)。

输出

按顺序输出“P”操作结果,每行包含一个数字。

样例输入

2 2 4C 1 1 2P 1 2C 2 2 2P 1 2

样例输出

21

解题思路

用线段树维护染色操作。
线段树每个节点维护两个值,colo和lazy。colo表示此节点表示区间的颜色集合(二进制状压),lazy为区间覆盖标记。
pushup时,当前结点的colo即左右儿子的colo相或的值。
复杂度 O(nlogn)

Code

#include<cstdio>#define lid id<<1#define rid id<<1|1#define mid ((tr[id].l+tr[id].r)>>1)using namespace std;inline int read(){    int x = 0;    bool fl = 1;    char ch = getchar();    while(ch < '0' || ch > '9'){        if(ch == '-')   fl = 0;        ch = getchar();    }    while(ch >= '0' && ch <= '9'){        x = (x << 1) + (x << 3) + ch - '0';        ch = getchar();    }    return fl ? x : -x;}const int N = 100005;int n, t, q, a, b, c, ans;char opt[2];inline int lowbit(int x){ return x & -x; }inline int countOne(int x){    int cnt = 0;    while(x){        cnt++;        x -= lowbit(x);    }    return cnt;}struct seg_tree{    int l, r, colo;    bool lazy;}tr[N<<2];void pushup(int id){    tr[id].colo = tr[lid].colo | tr[rid].colo;}void pushdown(int id){    if(tr[id].l != tr[id].r && tr[id].lazy){        tr[lid].colo = tr[rid].colo = tr[id].colo;        tr[lid].lazy = tr[rid].lazy = 1;        tr[id].lazy = 0;    }}void build(int id, int l, int r){    tr[id].l = l, tr[id].r = r;    tr[id].colo = (1 << 1);    tr[id].lazy = 1;    if(tr[id].l == tr[id].r)    return;    build(lid, l, mid);    build(rid, mid+1, r);    pushup(id);}void modify(int id, int l, int r, int c){    pushdown(id);    if(tr[id].l == l && tr[id].r == r){        tr[id].colo = (1 << c);        tr[id].lazy = 1;        return;    }    if(r <= mid)    modify(lid, l, r, c);    else if(l > mid)    modify(rid, l, r, c);    else    modify(lid, l, mid, c), modify(rid, mid+1, r, c);    pushup(id);}void query(int id, int l, int r){    pushdown(id);    if(tr[id].l == l && tr[id].r == r){        ans |= tr[id].colo;        return;    }    if(r <= mid)    query(lid, l, r);    else if(l > mid)    query(rid, l, r);    else    query(lid, l, mid), query(rid, mid+1, r);}int main(){    n = read(), t = read(), q = read();    build(1, 1, n);    while(q--){        scanf("%s", opt);        a = read(), b = read();        if(a > b)   a ^= b, b ^= a, a ^= b;        if(opt[0] == 'C'){            c = read();            modify(1, a, b, c);        }        else if(opt[0] == 'P'){            ans = 0;            query(1, a, b);            printf("%d\n", countOne(ans));        }    }    return 0;}