题目大意:
第一行给出两个整数n,m,n代表的是数组的大小,m代表询问的个数,对于每个询问有两种形式,
1 x y 表示的是将数组a[x]改为y,2 x y 表示的是查询从x到y的序列中不能表示出的最小的数是多少,这个题目的推导在我前几天写的博客里面有提到,有兴趣的可以去看一下【题目链接】现在问题的落脚点就是怎么求一段区间的和了,因为这个数组中有n个值,那么就代表着权值线段树有n+1个版本,如果第i个版本更新了,那么很显然(i,n)的所有版本都要给他更新,这时候复杂度可就大了,咱们可以考虑用树状数组优化这个过程,就是优化每次更新的下标,其实跟传统的一样,只是树状数组的值是一棵棵权值线段树,具体请看代码吧:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 200010;
typedef long long LL;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
void write(int x) {
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int n,q;
struct node {
int l,r;
LL sum;
};
int A[30],B[30],cnt1,cnt2;
int idx,root[N],a[N];
node tr[N<<7];
inline int lowbit(int x) {
return x & -x;
}
void insert(int &k,int l,int r,int pos,int val) {
if(!k) k = ++idx;
tr[k].sum += val;
if(l == r) return;
int mid = l + r >> 1;
if(pos <= mid) insert(tr[k].l,l,mid,pos,val);
else insert(tr[k].r,mid+1,r,pos,val);
}
LL query(int l,int r,int L,int R) {
if(l >= L && r <= R) {
LL ans = 0;
for(int i=1; i<=cnt1; i++) ans -= tr[A[i]].sum;
for(int i=1; i<=cnt2; i++) ans += tr[B[i]].sum;
return ans;
}
int mid = l + r >> 1;
int A1[30],B1[30];
LL ans = 0;
if(mid >= L) {
for(int i=1; i<=cnt1; i++) A1[i] = A[i],A[i] = tr[A[i]].l;
for(int j=1; j<=cnt2; j++) B1[j] = B[j],B[j] = tr[B[j]].l;
ans += query(l,mid,L,R);
for(int i=1; i<=cnt1; i++) A[i] = A1[i];
for(int j=1; j<=cnt2; j++) B[j] = B1[j];
}
if(R > mid) {
for(int i=1; i<=cnt1; i++) A1[i] = A[i],A[i] = tr[A[i]].r;
for(int j=1; j<=cnt2; j++) B1[j] = B[j],B[j] = tr[B[j]].r;
ans += query(mid+1,r,L,R);
for(int i=1; i<=cnt1; i++) A[i] = A1[i];
for(int j=1; j<=cnt2; j++) B[j] = B1[j];
}
return ans;
}
int main() {
n = read();
q = read();
for(int i=1; i<=n; i++) {
a[i] = read();
for(int j=i; j<=n; j+=lowbit(j)) {
insert(root[j],1,N,a[i],a[i]);
}
}
while(q--) {
int op = read();
if(op == 1) {
int x = read(),y = read();
for(int j=x; j<=n; j+=lowbit(j)) {
insert(root[j],1,N,a[x],-a[x]);
}
a[x] = y;
for(int j=x; j<=n; j+=lowbit(j)) {
insert(root[j],1,N,a[x],a[x]);
}
} else {
int l = read(),r = read();
cnt1 = cnt2 = 0;
for(int i=l-1; i; i-=lowbit(i)) A[++cnt1] = root[i];
for(int j=r; j; j-=lowbit(j)) B[++cnt2] = root[j];
LL st = 0,pre = 0;
while(1){
st = query(1,N,1,min(st+1,1ll*N));
if(st == pre) break;
pre = st;
}
printf("%lld\n", st + 1);
}
}
return 0;
}