C POJ 2777 Count Color 区间更新+压缩

本文介绍了一种使用位运算和延迟标记技术来高效处理区间更新和区间颜色计数的问题。通过构建特殊的树状数据结构,可以快速响应查询和更新请求,特别适用于颜色变化频繁且数量有限的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有两种操作,一个是更新区间内颜色,一个是询问区间内不同颜色的个数

因为颜色最多只有30种,所以把区间内颜色数压成一个数字即可,如果(1<<i)为1的话,就表示有这个颜色,更新时只要将儿子的这个值或运算一下就好了

因为是区间更新,所以再加个延时标记就好了。

/*===============*\
| *** *** *** *** |
|  *  **  *   * * |
| *** *** *   *** |
|    ID: ZERO     |
|    LANG: C++    |
\*===============*/
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <string>
#include <cassert>
using namespace std;
#define mod (int)(1e9+7)
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define maxn 100001
int col[maxn<<2];
bool up[maxn<<2];
int upit[maxn<<2];
void PushUP(int rt) { //向上更新
    col[rt] = col[rt<<1]|col[rt<<1|1];
}
void PushDown(int rt,int l,int r,int now){ //向下更新
    col[now]=col[rt];
    if(l!=r){
        up[now]=true;
        upit[now]=col[rt];
    }
}
void build(int co,int l,int r,int rt) {//建树
    up[rt]=false;
    if (l == r) {
        col[rt]=co;
        return ;
    }
    int m = (l + r) >> 1;
    build(co,lson);
    build(co,rson);
    PushUP(rt);
}
void update(int ll,int rr,int sc,int l,int r,int rt) {//更新
    if (l >=ll && r<=rr) {
        col[rt] = sc;
        if(l!=r) {up[rt]=true;upit[rt]=sc;}  //延时标记
        return ;
    }
    int m=(l+r) >> 1;//middle
    if(up[rt]){//触发延时标记
        PushDown(rt,lson);
        PushDown(rt,rson);
        up[rt]=false;
    }
    
    if (ll<=m&&rr>=l)     update(ll,rr , sc , lson);
    if (ll<=r&&rr>=m+1) update(ll,rr , sc , rson);
    PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) {//询问
    if (L <= l && r <= R) {
        return col[rt];
    }
    int m=(l+r) >> 1;//middle
    if(up[rt]){
        PushDown(rt,lson);
        PushDown(rt,rson);
        up[rt]=false;
    }
    
    int ret = 0;
    if (L <= m) ret = ret|query(L,R,lson);
    if (R > m) ret = ret|query(L,R,rson);
    return ret;
}
char s[2];
int main(){
    int n,m,t;
    while (~scanf("%d%d%d",&n,&t,&m)) {
        build(1,1,n,1);//建树
        while (m--) {
            int l,r,co;
            scanf("%s%d%d",s,&l,&r);
            int tt;
            if(l>r) tt=l,l=r,r=tt;// A may be larger than B 这条件你妹的!
            if(s[0]=='C'){
                scanf("%d",&co);
                update(l,r,1<<(co-1),1,n,1);
            }
            else{
                int nn=query(l,r,1,n,1),ans=0;
                for(int i=0;i<t;i++){
                    if(nn&(1<<i)) ans++;
                }
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值