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\n",ans[i]);
122 return 0;
123 }
来源:oschina
链接:https://my.oschina.net/u/4340488/blog/4039774