CodeForces - 940F Machine Learning (带修改莫队+离散化)

Machine Learning

 

You come home and fell some unpleasant smell. Where is it coming from?

You are given an array a. You have to answer the following queries:

  1. You are given two integers l and r. Let ci be the number of occurrences of i in al: r, where al: r is the subarray of a from l-th element to r-th inclusive. Find the Mex of {c0, c1, ..., c109}
  2. You are given two integers p to x. Change ap to x.

The Mex of a multiset of numbers is the smallest non-negative integer not in the set.

Note that in this problem all elements of a are positive, which means that c0 = 0 and 0 is never the answer for the query of the second type.

Input

The first line of input contains two integers n and q (1 ≤ n, q ≤ 100 000) — the length of the array and the number of queries respectively.

The second line of input contains n integers — a1, a2, ..., an (1 ≤ ai ≤ 109).

Each of the next q lines describes a single query.

The first type of query is described by three integers ti = 1, liri, where 1 ≤ li ≤ ri ≤ n — the bounds of the subarray.

The second type of query is described by three integers ti = 2, pixi, where 1 ≤ pi ≤ n is the index of the element, which must be changed and 1 ≤ xi ≤ 109 is the new value.

Output

For each query of the first type output a single integer  — the Mex of {c0, c1, ..., c109}.

Example

Input

10 4
1 2 3 1 1 2 2 2 9 9
1 1 1
1 2 8
2 7 1
1 2 8

Output

2
3
2

Note

The subarray of the first query consists of the single element — 1.

The subarray of the second query consists of four 2s, one 3 and two 1s.

The subarray of the fourth query consists of three 1s, three 2s and one 3.

题目链接:http://codeforces.com/problemset/problem/940/F

题目大意:给出长度为n的数列,有m个操作,1 x y 表示查询区间 [ l ,r ] 中 相同数字出现的次数,其中没有出现的次数的最小值(不包括0),例如:区间内的数为 1 1 2 2 2 ,1出现2次,2出现3次,出现的次数为 2  3,所以最小的没出现过的次数是1,     2 x y 表示把a[x] 修改为 y

思路:ai到10^9 离散化,然后就是带修改莫队的模板

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
using namespace std;
const int N=300005;
int a[N],e[N],f[N];
int k,c[N],d[N],b[N];
map<int,int>ma;
struct que
{
    int l,r,posl,posr,ts,id;
}q[N];
struct modi
{
    int pos,x,pre;
}mo[N];
bool cmp(que a,que b)
{
    if(a.posl==b.posl)
    {
        if(a.posr==b.posr)
            return a.ts<b.ts;
        return a.posr<b.posr;
    }
    return a.posl<b.posl;
}
void update(int x,int p)
{
    if(x==0) return;
    if(c[x]>0) d[c[x]]--;
    c[x]+=p;
    if(c[x]>0) d[c[x]]++;
}
void modify(int x,int p,int l,int r)
{
    if(x>=l&&x<=r)
    {
        update(a[x],-1);
        update(p,1);
    }
    a[x]=p;
}
int fun()
{
    for(int i=1;;i++) if(d[i]<1) return i;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int p=pow(n,0.666666);
    if(p==0) p=1;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),e[i]=f[i]=a[i];
    //离散化
    sort(f+1,f+1+n);
    k=unique(f+1,f+1+n)-(f+1);
    for(int i=1;i<=k;i++) ma[f[i]]=i;
    for(int i=1;i<=n;i++) e[i]=a[i]=ma[a[i]];
    
    int tot=0,cnt=0,len=k;
    int op,x,y;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&op,&x,&y);
        if(op==1)
        {
            q[tot].l=x,q[tot].posl=x/p;
            q[tot].r=y,q[tot].posr=y/p;
            q[tot].id=tot,q[tot++].ts=cnt;
        }
        else
        {
            if(!ma[y]) ma[y]=++len; //离散化
            y=ma[y];
            mo[++cnt].pos=x,mo[cnt].pre=e[x];
            mo[cnt].x=y,e[x]=y;
        }
    }
    sort(q,q+tot,cmp);
    int l=0,r=0,cn=0;
    for(int i=0;i<tot;i++)
    {
        while(cn<q[i].ts) modify(mo[cn+1].pos,mo[cn+1].x,l,r),cn++;
        while(cn>q[i].ts) modify(mo[cn].pos,mo[cn].pre,l,r),cn--;
        while(l<q[i].l) update(a[l++],-1);
        while(l>q[i].l) update(a[--l],1);
        while(r>q[i].r) update(a[r--],-1);
        while(r<q[i].r) update(a[++r],1);
        b[q[i].id]=fun();
    }
    for(int i=0;i<tot;i++)
        printf("%d\n",b[i]);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值