CF940F Machine Learning 带修改莫队

排序函数一定要注意: 

struct query
{
    int l,r,id,t;    
    query(int l=0,int r=0):l(l),r(r){} 
    bool operator<(query b) const 
    {
        return l/B==b.l/B?(r/B==b.r/B?t<b.t:r<b.r):l<b.l;       
    }
}q[N]; 

这里千万不能写错,否则整个时间复杂度就假了~

一般来说,带修改莫队中块的大小取在 $n^{0.6666}$ 来说是比较优的.   

这道题中,你发现 $mex$ 的大小不超过 $\sqrt n$,所以我们可以直接暴力求. 

code: 

#include <bits/stdc++.h>   
#define N 300005    
#define ll long long  
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;      
int n,m,tot,opcnt,qcnt,B,now;          
int a[N],A[N],output[N],cnt[N],mex[N];            
struct query
{
    int l,r,id,t;    
    query(int l=0,int r=0):l(l),r(r){} 
    bool operator<(query b) const 
    {
        return l/B==b.l/B?(r/B==b.r/B?t<b.t:r<b.r):l<b.l;       
    }
}q[N]; 
struct change
{
    int p,x;   
    change(int p=0,int x=0):p(p),x(x){}  
}c[N];   
void add(int num) 
{     
    --mex[cnt[num]];           
    ++mex[++cnt[num]];         
}
void del(int num) 
{   
    --mex[cnt[num]];  
    ++mex[--cnt[num]];             
}
void update(int id,int t) 
{
    if(c[t].p>=q[id].l&&c[t].p<=q[id].r) 
    {
        del(a[c[t].p]);  
        add(c[t].x);        
    }   
    swap(c[t].x, a[c[t].p]);     
}
int getans() 
{
    int i,j; 
    for(i=1;mex[i]>0;++i);   
    return i;    
}
int main() 
{ 
    int i,j,l=2,r=1;       
    // setIO("input");       
    scanf("%d%d",&n,&m);   
    B=pow(n,0.6666);   
    for(i=1;i<=n;++i) 
    {
        scanf("%d",&a[i]); 
        A[++tot]=a[i];   
    }
    for(i=1;i<=m;++i) 
    {
        int op,a,b;    
        scanf("%d%d%d",&op,&a,&b);    
        if(op==1) 
        {
            ++qcnt;       
            q[qcnt]=query(a,b);  
            q[qcnt].id=qcnt; 
            q[qcnt].t=opcnt;   
        }
        else 
        {
            ++opcnt;   
            c[opcnt]=change(a,b);    
            A[++tot]=b;     
        }
    }
    sort(A+1,A+1+tot);   
    for(i=1;i<=n;++i) a[i]=lower_bound(A+1,A+1+tot,a[i])-A;     
    for(i=1;i<=opcnt;++i) c[i].x=lower_bound(A+1,A+1+tot,c[i].x)-A;       
    sort(q+1,q+1+qcnt);    
    for(i=1;i<=qcnt;++i) 
    {
        for(;l>q[i].l;) add(a[--l]);     
        for(;r<q[i].r;) add(a[++r]);   
        for(;l<q[i].l;) del(a[l++]);   
        for(;r>q[i].r;) del(a[r--]);   
        for(;now<q[i].t;) update(i, ++now);     
        for(;now>q[i].t;) update(i, now--);   
        output[q[i].id]=getans();    
    }
    for(i=1;i<=qcnt;++i) printf("%d\n",output[i]);   
    return 0;     
}

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值