洛谷-P1903 数颜色 分块 bitset

题目

题目链接

题意

给你一个数列代表不同的颜色(可以修改)。
询问一段区间内有多少种颜色。

题解

很容易想到的就是线段树来维护bitset。

这里为了练习,使用分块维护bitset。

* 事实上线段树可以看成是无限分块。*

修改的时候直接暴力将被修改位置所在的块重新计算,形成新的bitset。

查询的时候,直接按块合并bitset即可。

注意细节:由于bitset不能开太大,因此有必要将给出的颜色进行离散化。

我采用的方法是使用unordered_map进行离散化,简单易行。

代码

#include <unordered_map>
#include <bits/stdc++.h>
using namespace std;
int n,m,L,R;
int a[10007];
bitset<12007> block[107];
bitset<12007> now;
int Base = 100;
unordered_map<int,int> mpid;
inline int getid(int x){
    if(mpid.count(x)) return mpid[x];
    return mpid[x] = mpid.size()+1;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;++i){
        if(i % Base == 0 && i != 0) {
            block[i/Base-1] = now;
            now.reset();
        }
        scanf("%d",&a[i]);
        now.set(getid(a[i]));
    }
    block[n/Base] = now;
    char op;
    while(m--){
        scanf(" %c%d%d",&op,&L,&R);
        if(op == 'Q'){
            now.reset();
            for(;L % Base != 0 && L <= R;++L){
                now.set(getid(a[L]));
            }

            for(;(R+1) % Base != 0 && R >= L;--R){
                now.set(getid(a[R]));
            }

            if(L >= R) {
                printf("%d\n",now.count());
                continue;
            }

            int bl = L / Base,br = R / Base;
            for(;bl <= br;++bl)
                now |= block[bl];

            printf("%d\n",now.count());
        }
        else {
            a[L] = R;
            int bl = L / Base;
            block[bl].reset();

            for(int i = bl*Base;i < (bl+1)*Base;++i)
                block[bl].set(getid(a[i]));
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值