2120: 数颜色【带修莫队】

本文探讨了在多个区间内进行颜色种类数的询问问题,提供了详细的算法分析和实现代码,采用带修莫队算法解决单点修改颜色的场景。

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

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

题意:多个区间询问,询问[l,r]中颜色的种类数。可以单点修改颜色。

分析:

一个裸的带修莫队

代码:

#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
int n,m,b[10500],s[10500],now[10500],Time,l,r,ans,po[10500],sum[1050000];
struct node
{
    int l,r,time,id;
}v[10500];
struct Change
{
    int pos,now,pre;
}h[10500];
bool com1 (node aa,node bb)
{
    return b[aa.l]==b[bb.l]?(b[aa.r]==b[bb.r]?aa.time<bb.time:aa.r<bb.r):(aa.l<bb.l);
}
void uppdate(int pos,int add)
{
    sum[s[pos]]+=add;
    if(sum[s[pos]]==0&&add<0)
        ans--;
    else
    if(sum[s[pos]]==1&&add>0)
    ans++;
}
void update(int x,int now)
{
    if(l<=x&&r>=x)
    {
        uppdate(x,-1);
        s[x]=now;
        uppdate(x,1);
    }
    else
        s[x]=now;
}
int main()
{
    int i,j,tt,Size;
    scanf("%d%d",&n,&m);
    Size=pow(n,0.66666);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&s[i]);
        now[i]=s[i];
        b[i]=i/Size+1;
    }
    char cc;
    int aa,bb,t;
    Time=0;
    tt=0;
    for(i=1;i<=m;i++)
    {
        scanf(" %c %d%d",&cc,&aa,&bb);
        if(cc=='Q'){v[++tt]=(node){aa,bb,Time,tt};}
        else
        if(cc=='R')
        {
            h[++Time]=(Change){aa,bb,now[aa]};
            now[aa]=bb;
        }
    }
    t=0;
    l=1;
    r=0;
    sort(v+1,v+1+tt,com1);
    for(i=1;i<=tt;i++)
    {
        while(t<v[i].time){
            update(h[t+1].pos,h[t+1].now);
            t++;
        }
        while(t>v[i].time){
            update(h[t].pos,h[t].pre);
            t--;
        }
        while(l<v[i].l){
            uppdate(l,-1);
            l++;
        }
        while(l>v[i].l){
            uppdate(l-1,1);
            l--;
        }
        while(r<v[i].r){
            uppdate(r+1,1);
            r++;
        }
        while(r>v[i].r){
            uppdate(r,-1);
            r--;
        }
        po[v[i].id]=ans;
    }
    for(i=1;i<=tt;i++)
    printf("%d\n",po[i]);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值