[poj2777] Count Color(線段樹+狀壓)

題目大意

描述

給一塊長爲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 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

樣例輸出

2
1

解題思路

用線段樹維護染色操作。
線段樹每個節點維護兩個值,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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章