题目链接:点击这里
题目大意:
给定一个长度为
n
n
n 的序列
a
1
,
a
2
,
.
.
.
,
a
n
a_1,a_2,...,a_n
a1,a2,...,an
序列支持两种操作:
- 询问你 [ l , r ] [l,r] [l,r] 中数字出现次数的 m e x mex mex
- 将一个位置的数字替换成另一个数字
题目分析:
离散化时是把初始序列和所有修改后的数据全离散化。
数字出现次数的
m
e
x
mex
mex 的求法:因为序列只有
n
=
1
e
5
n=1e5
n=1e5 个数字,数字出现次数的
m
e
x
mex
mex 的最大值最坏情况为
n
\sqrt n
n ,所以可以暴力求解每次复杂第为
O
(
n
)
O(\sqrt n)
O(n) ,加上待修改的操作所需的带修莫队,故总时间复杂度为
O
(
n
5
3
)
O(n^{\frac 5 3})
O(n35)
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 2e5+5;
const int maxm = 1e6;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
int n,m,block,a[maxn],cntq,cntc,cnt[maxn],num[maxn],ans[maxn];
vector<int>v;
struct query{
int l,r,t,id;
friend bool operator < (const query &a,const query &b)
{
return a.l/block ^ b.l/block ? a.l < b.l : a.r/block ^ b.r/block ? a.r<b.r : a.t < b.t;
}
}q[maxn];
struct node{
int pos,val;
}c[maxn];
void add(int pos)
{
--num[cnt[pos]];
num[++cnt[pos]]++;
}
void del(int pos)
{
--num[cnt[pos]];
num[--cnt[pos]]++;
}
int main()
{
n = read(),m = read();
block = pow(n,2.0/3.0);
for(int i = 1;i <= n;i++)
{
a[i] = read();
v.push_back(a[i]);
}
for(int i = 1;i <= m;i++)
{
int opt = read();
if(opt&1)
{
q[++cntq].l = read(),q[cntq].r = read();
q[cntq].t = cntc;
q[cntq].id = cntq;
}
else {
c[++cntc].pos = read();
c[cntc].val = read();
v.push_back(c[cntc].val);
}
}
sort(q+1,q+cntq+1);
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i = 1;i <= n;i++)
a[i] = lower_bound(v.begin(),v.end(),a[i])-v.begin();
for(int i = 1;i <= cntc;i++)
c[i].val = lower_bound(v.begin(),v.end(),c[i].val)-v.begin();
int l = 1,r = 0,t = 0;
for(int i = 1;i <= cntq;i++)
{
int ql = q[i].l,qr = q[i].r;
while(l < ql) del(a[l++]);
while(l > ql) add(a[--l]);
while(r < qr) add(a[++r]);
while(r > qr) del(a[r--]);
while(t < q[i].t)
{
t++;
if(ql<=c[t].pos && qr>=c[t].pos)
{
del(a[c[t].pos]);
add(c[t].val);
}
swap(a[c[t].pos],c[t].val);
}
while(t > q[i].t)
{
if(ql<=c[t].pos && qr>=c[t].pos)
{
del(a[c[t].pos]);
add(c[t].val);
}
swap(a[c[t].pos],c[t].val);
t--;
}
for(ans[q[i].id] = 1;num[ans[q[i].id]];ans[q[i].id]++);
}
for(int i = 1;i <= cntq;i++)
printf("%d\n",ans[i]);
return 0;
}