BZOJ---2120:数颜色【带修莫队】

这篇博客详细介绍了如何在莫队算法的基础上处理数颜色问题并添加修改操作。博主分析了如何记录每个询问的修改序数,并按块划分以达到复杂度优化,链接指向具体的题目。提供了实现代码。
摘要由CSDN通过智能技术生成

题目:

https://www.lydsy.com/JudgeOnline/problem.php?id=2120

分析:

在普通的莫队上,加上了修改操作,只需要在原来的基础上加一维时间,对于每一个询问记录下它是第几次修改后的询问,统计答案时,如果已经修改的序数 < 当前询问的修改序数,那么就将没有修改的执行修改操作,如果多修改了几次,则修改回去

这里要将1 - N 分成(N^(2/3))块,复杂度证明参考:戳戳戳~~

代码:

#include <bits/stdc++.h>
 
using namespace std;
const int MAXN = 1e4+14;
struct Segment{
    int l,r,t,id;
}se[MAXN];
struct Revise{
    int pos,col;
}re[MAXN];
int n,m,res,block,T,L,R,c[MAXN],vis[MAXN*100],ans[MAXN];
inline void revise(int T,int pos,int color){
    if(L <= pos && pos <= R){
        if(--vis[c[pos]] == 0) res--;
        if(++vis[color] == 1) res++;
    }
    re[T].col = c[pos];                 //方便修改回原来的颜色
    c[pos] = color;
}
inline void add(int x){
    if(!vis[c[x]]) res++;
    vis[c[x]]++;
}
inline void del(int x){
    if(vis[c[x]] == 1) res--;
    vis[c[x]] --;
}
bool cmp(Segment a,Segment b){
    return a.l/block==b.l/block?(a.r/block==b.r/block?a.t<b.t:a.r<b.r):a.l<b.l;
}
int main(){
    cin >> n >> m;
    block = pow(n,0.66666);
    for(int i = 1;i <= n; ++i) cin >> c[i];
    char op;
    int qlen = 1,rlen = 0; 
    while(m--){
        cin >> op;
        if(op == 'Q'){
            cin >> se[qlen].l >> se[qlen].r;
            se[qlen].id = qlen;
            se[qlen].t = rlen;
            qlen++;
        }
        else{
            ++rlen;
            cin >> re[rlen].pos >> re[rlen].col;
        }
    }
    sort(se+1,se+qlen+1,cmp);
    L = 1,R = 0,T = 0;
    for(int i = 1;i <= qlen; ++i){
        while(T < se[i].t)  ++T,revise(T,re[T].pos,re[T].col);
        while(T > se[i].t)  revise(T,re[T].pos,re[T].col),--T;
        while(L < se[i].l) del(L),++L;
        while(L > se[i].l) --L,add(L); 
        while(R < se[i].r) ++R,add(R);
        while(R > se[i].r) del(R),--R;
        ans[se[i].id] = res;
    }
    for(int i = 1;i < qlen; ++i) cout << ans[i] << '\n';
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值