Count Color(线段树+位运算)

这是之前比赛的一道题目,HD训练题上又遇到了,直接A了,其实就是将求和操作变成|=运算符,用位运算压缩T种颜色,这样每个结点上维护的就是其所覆盖的颜色种类数。

细节参见代码:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 100000 + 5;
int T,n,q,y11,y22,v,kase=0,_sum,sumv[3*maxn],setv[maxn*3];
void pushdown(int o) {
    int lc = o*2, rc = o*2+1;
    if(setv[o] >= 0) {
        setv[lc] = setv[rc] = setv[o];
        setv[o] = -1;
    }
}
void maintain(int o, int L, int R) {
    int lc = o*2, rc = o*2+1;
    sumv[o] = 0;
    if(R > L) {
        sumv[o] |= sumv[lc];
        sumv[o] |= sumv[rc];
    }
    if(setv[o]>=0) sumv[o] = setv[o];
}
void update(int o, int L, int R) {
    int lc = o*2, rc = o*2+1;
    if(y11 <= L && y22 >= R) {
        setv[o] = (1< M) update(rc, M+1, R); else maintain(rc, M+1, R);
    }
    maintain(o, L, R);
}
void query(int o, int L, int R) {
    if(setv[o] >= 0) {
        _sum |= setv[o];
    } else if(y11 <= L && y22 >= R) {
        _sum |= sumv[o];
    } else {
        int M = L + (R-L)/2;
        if(y11 <= M) query(o*2, L, M);
        if(y22 > M) query(o*2+1, M+1, R);
    }
}
char s[10];
int main() {
    while(~scanf("%d%d%d",&n,&T,&q)) {
        v = 1; y11 = 1; y22 = n;
        update(1,1,n);
        while(q--) {
            scanf("%s%d%d",s,&y11,&y22);
            if(s[0] == 'C') {
                scanf("%d",&v);
                update(1,1,n);
            }
            else {
                _sum = 0;
                query(1,1,n);
                int ans = 0;
                for(int i = 1; i <= T; i++) {
                    if(_sum & (1<

你可能感兴趣的:(线段树和树状数组,uva解题报告)