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:
- 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}
- 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.
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, li, ri, where 1 ≤ li ≤ ri ≤ n — the bounds of the subarray.
The second type of query is described by three integers ti = 2, pi, xi, where 1 ≤ pi ≤ n is the index of the element, which must be changed and 1 ≤ xi ≤ 109 is the new value.
For each query of the first type output a single integer — the Mex of {c0, c1, ..., c109}.
10 4
1 2 3 1 1 2 2 2 9 9
1 1 1
1 2 8
2 7 1
1 2 8
2
3
2
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.
大意:给出一个序列,两种操作。
1.询问一个区间内,把每种元素的个数组成一个集合,这个集合的mex值(不在集合中的最小值)。
2.单点修改。
题解:
莫队算法:
题目给出数值的大小过大,但是实际出现过的最多200000个,离散化,把出现过的数从小到大排列,和1——200000,一一对应。
这样题目中的每个数值都可以用1——200000中的数等价替换。
然后就是带修改的莫队。
其实就是多加了一维时间,三维和二维类比一下,就是先按照左端点分块,再按照右端点分块,块中时间单调。
块的大小需要时n^(2/3),如果还是sqrt(n)会TLE。
因为块的大小是n^(2/3)的时候复杂度最低,通过考虑每种移动方式的复杂度可以证明,详情请移步大神博客:
https://www.luogu.org/blog/user12668/solution-p1903
1 /* 2 Welcome Hacking 3 Wish You High Rating 4 */ 5 #include<iostream> 6 #include<cstdio> 7 #include<cstring> 8 #include<ctime> 9 #include<cstdlib> 10 #include<algorithm> 11 #include<cmath> 12 #include<string> 13 #include<map> 14 using namespace std; 15 int read(){ 16 int xx=0,ff=1;char ch=getchar(); 17 while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();} 18 while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();} 19 return xx*ff; 20 } 21 const int maxn=100010; 22 int N,M,block,a[maxn],b[maxn],belong[maxn]; 23 struct query{ 24 int L,R,tim,id; 25 bool friend operator<(const query&A,const query&B){ 26 if(belong[A.L]!=belong[B.L]) 27 return A.L<B.L; 28 if(belong[A.R]!=belong[B.R]) 29 return A.R<B.R; 30 return A.tim<B.tim; 31 } 32 }Q[maxn]; 33 struct change{ 34 int pos,x,y; 35 }C[maxn]; 36 int tp1,tp2,tp; 37 int pm[maxn*2],arg[3][maxn]; 38 map<int,int>mp; 39 int rk[maxn*2],tot; 40 int cnt[maxn*2],siz[maxn],ans[maxn]; 41 int x,y,z; 42 inline void add(int i){ 43 siz[cnt[i]]--; 44 siz[++cnt[i]]++; 45 } 46 inline void del(int i){ 47 siz[cnt[i]]--; 48 siz[--cnt[i]]++; 49 } 50 inline void change_add(int i){ 51 if(C[i].pos>=x&&C[i].pos<=y){ 52 del(C[i].x); 53 add(C[i].y); 54 } 55 a[C[i].pos]=C[i].y; 56 } 57 inline void change_del(int i){ 58 if(C[i].pos>=x&&C[i].pos<=y){ 59 del(C[i].y); 60 add(C[i].x); 61 } 62 a[C[i].pos]=C[i].x; 63 } 64 int main(){ 65 //freopen("in.txt","r",stdin); 66 N=read(),M=read(); 67 for(int i=1;i<=N;i++) 68 pm[++tp]=b[i]=read(); 69 70 for(int i=1;i<=M;i++){ 71 for(int j=0;j<=2;j++) 72 arg[j][i]=read(); 73 if(arg[0][i]==2) 74 pm[++tp]=arg[2][i]; 75 } 76 77 sort(pm+1,pm+1+tp); 78 for(int i=1;i<=tp;i++) 79 if(!mp[pm[i]]) 80 mp[pm[i]]=++tot,rk[tot]=pm[i]; 81 82 for(int i=1;i<=N;i++) 83 a[i]=b[i]=mp[b[i]]; 84 for(int i=1;i<=M;i++) 85 if(arg[0][i]==2) 86 arg[2][i]=mp[arg[2][i]]; 87 88 for(int i=1;i<=M;i++) 89 if(arg[0][i]==1) 90 Q[++tp1].tim=tp2,Q[tp1].L=arg[1][i],Q[tp1].R=arg[2][i],Q[tp1].id=tp1; 91 else 92 C[++tp2].pos=arg[1][i],C[tp2].x=b[C[tp2].pos],C[tp2].y=arg[2][i],b[C[tp2].pos]=arg[2][i]; 93 94 block=(int)pow(N+0.5,2.0/3);//caution 95 96 for(int i=1;i<=N;i++) 97 belong[i]=(i-1)/block+1; 98 sort(Q+1,Q+1+tp1); 99 x=Q[1].L,y=Q[1].L-1,z=0; 100 for(int i=1;i<=tp1;i++){ 101 for(;x<Q[i].L;x++) 102 del(a[x]); 103 for(;x>Q[i].L;x--) 104 add(a[x-1]); 105 for(;y<Q[i].R;y++) 106 add(a[y+1]); 107 for(;y>Q[i].R;y--) 108 del(a[y]); 109 for(;z<Q[i].tim;z++) 110 change_add(z+1); 111 for(;z>Q[i].tim;z--) 112 change_del(z); 113 114 for(int j=1;;j++) 115 if(!siz[j]){ 116 ans[Q[i].id]=j; 117 break; 118 } 119 } 120 for(int i=1;i<=tp1;i++) 121 printf("%d ",ans[i]); 122 return 0; 123 }