题意
n个数,两种操作,一种是修改某个数,一种的求一段区间的数,他们设子集所能表示的数的 m e x mex mex
题解
求
m
e
x
mex
mex ,先看能不能表示出1,求下小于1 的数的和,若为0 ,这答案为1,否则继续,设上一次求出的和为 x,说明 数字
1
−
x
1-x
1−x 都可以 被表示,再求小于 x+1 的数的和,若没有增加,说明 x+1 不能被表示,否则继续重复上述操作。
用主席树带修改即可
代码
#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi 3.141592653589793
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef pair<int,int> pp;
int rt[N],tot;
int n,m;
int w[N];
struct PST{
int ls[N*150],rs[N*150],l1[20],l0[20],cnt,S,t,w[2][20][20],p[2];
LL sum[N*150];
void init(int x,int Max){S=x;cnt=0;tot=Max;}
inline void ins(int &i,int x,int val,int l=1,int r=tot){
if(!i) i=++cnt; int j=i;
while(l<r){
sum[j]+=val*x;
int mid=l+r>>1;
if (x<=mid) r=mid,j=ls[j]?ls[j]:ls[j]=++cnt;
else l=mid+1,j=rs[j]?rs[j]:rs[j]=++cnt;
}
sum[j]+=val*x;
}
//将位置pos的值删去/加上,val=-1/1
inline void Modify(int pos,int x,int val){
for(int i=pos;i<=S;i+=i&-i) ins(rt[i],x,val);
}
//int w[0][20][20],p[2];
LL ask(int x,int y,int d,int l=1,int r=tot){
int v=d+1;
if (l==x&&y==r){
LL s=0; for(int i=1;i<=t;i++) s+=sum[w[1][d][i]],s-=sum[w[0][d][i]];
return s;
}
int mid=l+r>>1;
if (y<=mid) {
for(int i=1;i<=t;i++) w[0][v][i]=ls[w[0][d][i]],w[1][v][i]=ls[w[1][d][i]];
return ask(x,y,v,l,mid);
}else
if (x>mid) {
for(int i=1;i<=t;i++) w[0][v][i]=rs[w[0][d][i]],w[1][v][i]=rs[w[1][d][i]];
return ask(x,y,v,mid+1,r);
}else{
for(int i=1;i<=t;i++) w[0][v][i]=ls[w[0][d][i]],w[1][v][i]=ls[w[1][d][i]];
LL t1=ask(x,mid,v,l,mid);
for(int i=1;i<=t;i++) w[0][v][i]=rs[w[0][d][i]],w[1][v][i]=rs[w[1][d][i]];
LL t2=ask(mid+1,y,v,mid+1,r);
return t1+t2;
}
}
//区间[l,r]范围为数值在[x,y]的个数
inline LL query(int l,int r,int x,int y){
p[0]=p[1]=0;memset(w,0,sizeof w);
for(int i=l-1;i;i-=i&-i) w[0][0][++p[0]]=rt[i];
for(int i=r;i;i-=i&-i) w[1][0][++p[1]]=rt[i];
t=max(p[0],p[1]);
return ask(x,y,0);
}
}PST;
int main(int argc, char const *argv[])
{
scc(n,m);
PST.init(n,2e5);
for(int i=1,x;i<=n;i++) scanf("%d",&x),PST.Modify(i,x,1),w[i]=x;
while(m--){
int op; sc(op);
if (op==1){
int x,y; scc(x,y);
PST.Modify(x,w[x],-1);
w[x]=y;
PST.Modify(x,w[x],1);
}else{
int L,R; scc(L,R);
LL t,sum=0;
do{
t=sum+1;
sum=PST.query(L,R,1,min(1ll*tot,t));
}while(sum>=t);
printf("%lld\n",sum+1);
}
}
return 0;
}