• CF940F


    要查询的是区间中每个数字出现次数的 mex,考虑到这个 mex 的判断是基于出现次数的,所以我们维护每个数字的出现次数和每种出现次数对应的数字。

    当删除或加入某个数时,我们将这个数对应的出现次数增减,同时将对应次数的数的个数也增减。

    每次询问的答案不是在增减过程中求出,也无法在增减过程中求出。
    处理完当前区间所有数对应的次数后,我们从小到大枚举次数,第一个出现的没有对应数字的次数就是当前询问的答案。

    至于修改操作,则与普通带修莫队无异,可以看这里,这里不多赘述。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define maxn 1000010
    //#define int long long
    
    using namespace std;
    
    int a[maxn],b[maxn];
    int n,m,Ans,len,L=1,R;
    int all,cntq,cntc,Now,id;
    int cnt[maxn],num[maxn],ans[maxn];
    struct question{int l,r,t,now;}q[maxn];
    struct change{int pos,val;}c[maxn];
    
    int read(){
    	int s=0,w=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-') w=1;ch=getchar();}
    	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
    	return s*w;
    }
    
    bool cmp(question a,question b){
        return (a.l/len)^(b.l/len)?a.l<b.l:(a.r/len)^(b.r/len)?a.r<b.r:a.t<b.t;
    }
    
    void Add(int x){
        num[cnt[x]]--;
        num[++cnt[x]]++;
    }
    
    void Del(int x){
        num[cnt[x]]--;
        num[--cnt[x]]++;
    }
    
    void Modify(int ti,int x){
        if(c[ti].pos>=q[x].l&&c[ti].pos<=q[x].r)
            Del(a[c[ti].pos]),Add(c[ti].val);
        swap(a[c[ti].pos],c[ti].val);
    }
    
    int main(){
        n=read();m=read();len=pow(n,2.0/3);
        for(int i=1;i<=n;i++)b[++id]=a[i]=read();
        for(int i=1,opt;i<=m;i++){
            opt=read();
            if(opt==1){
                q[++cntq].l=read();q[cntq].r=read();
                q[cntq].t=cntc;q[cntq].now=cntq;
            }
            else c[++cntc].pos=read(),c[cntc].val=read();
        }
        sort(b+1,b+id+1);all=unique(b+1,b+id+1)-b-1;
        for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+all+1,a[i])-b;
        sort(q+1,q+cntq+1,cmp);
        for(int i=1;i<=cntq;i++){
            while(L<q[i].l) Del(a[L++]);
            while(L>q[i].l) Add(a[--L]);
            while(R<q[i].r) Add(a[++R]);
            while(R>q[i].r) Del(a[R--]);
            while(Now<q[i].t) Modify(++Now,i);
            while(Now>q[i].t) Modify(Now--,i);
            for(ans[q[i].now]=1;num[ans[q[i].now]]>0;ans[q[i].now]++);
        }
        for(int i=1;i<=cntq;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    

    CF940F

  • 相关阅读:
    android操作数据库
    Android读写SD卡上的文件
    第四章 函数与程序结构
    getchar()与EOF
    NULL, '',0 '0'的区别
    TCPL 行计数
    行计数
    getchar()用法
    在C语言中,double、long、unsigned、int、char类型数据所占字节数
    队列——解密QQ号
  • 原文地址:https://www.cnblogs.com/KnightL/p/14700897.html
Copyright © 2020-2023  润新知