POJ 2777

传送门

 

题目要求支持两个操作

C x  y  v   将区间[x,y]内木块全染成v色。

P x  y   回答区间[x,y]中不同颜色的个数。 

 

思路:

下放标记,然后进行状态压缩。

对,就是这样。

压缩的状态中表示当前段存在哪几种颜色。

最后询问操作返回的是一个压缩的值。

这个时候我们就要统计返回值的二进制中1的个数。

可以用以下代码快速解决。

while(x){

  count++;

  x = x&(x-1);

}

至于为什么?

不赘述。

下面帖代码,有问题留言。

 

#include<cstdio>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 1000009
using namespace std;

int w[N<<2|1],add[N<<2|1];

void update(int rt){            //左子树与右子树合并
    w[rt] = (w[rt<<1]|w[rt<<1|1]);
}

void build(int l,int r,int rt){
    if(l == r){
        w[rt] |= 1;         //初始化为1
        add[rt] = 0;
        return;
    }
    int m = (l+r)>>1;
    build(lson);
    build(rson);
    update(rt);
}

void color(int l,int r,int rt,int v){
    w[rt] &= 0;
    w[rt] |= (1<<(v-1));
    add[rt] = v;
}

void push_col(int l,int r,int rt){
    if(add[rt]){                    //0代表没有标记,否则是标记了,那么下放标记
        int m = (l+r)>>1;
        color(lson,add[rt]);
        color(rson,add[rt]);
        add[rt] = 0;
    }
}

void modify(int l,int r,int rt,int nowl,int nowr,int v){
    if(nowl <= l && r <= nowr){
        color(l,r,rt,v);
        return;
    }
    push_col(l,r,rt);
    int m = (l+r)>>1;
    if(nowl <= m)modify(lson,nowl,nowr,v);
    if(m < nowr)modify(rson,nowl,nowr,v);
    update(rt);
}

int query(int l,int r,int rt,int nowl,int nowr){
    if(nowl <= l && r <= nowr)return w[rt];
    push_col(l,r,rt);
    int m = (l+r)>>1;
    long long  ans = 0;
    if(nowl <= m) ans |= query(lson,nowl,nowr);     //左边与右边要合并
    if(m < nowr)ans |= query(rson,nowl,nowr);
    return ans;
}

int read(){                             //读入优化
    int x = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9')ch = getchar();
    while(ch >= '0' && ch <= '9'){
        x =x * 10 + ch -'0';
        ch = getchar();
    }
    return x;
}

int main(){
    int n = read(),t = read(),m = read();
    build(1,n,1);
    while(m--){
        char cmd[2];
        scanf("%s",cmd);
        if(cmd[0] == 'C'){
            int x = read(),y = read(),v =read();
            if(x > y)swap(x,y);
            modify(1,n,1,x,y,v);
        }
        else {
            int x = read(),y =read();
            if(x > y)swap(x,y);
            int ans = query(1,n,1,x,y);
            int count = 0;
            while(ans){             //计算个数
                count++;
                ans = ans&(ans-1);
            }
            printf("%d\n",count);
        }
    }
    return 0;
}

 

posted @ 2017-11-01 19:59  君焰w  阅读(160)  评论(0编辑  收藏  举报