题目链接:http://codeforces.com/contest/940/problem/F
题解:因为a[i]的值范围有1e9,但操作的数不会超过2e5,离散化的到对应值的大小。然后用带修改莫队算法,复杂度 .
没学过莫队的可以看这个.
#include<bits/stdc++.h> #include<set> #include<iomanip> #include<iostream> #include<string> #include<cstring> #include<algorithm> #define pb push_back #define ll long long #define PI 3.14159265 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define eps 1e-7 typedef unsigned long long ull; const int mod=1e9+9; const ll inf=0x3f3f3f3f3f3f3f; const int maxn=1e5+50; using namespace std; int a[maxn],belong[maxn],block,ans=1,l=1,r=0,an[maxn],n,qq,cnt,cn[2*maxn],c[maxn]; struct que { int l,r,tim,id; }q[maxn]; struct cha { int p,now,old; }st[maxn]; int num[2*maxn]; bool cmp(que a,que b) { return belong[a.l]==belong[b.l]?belong[a.r]==belong[b.r]?a.tim<b.tim:a.r<b.r:a.l<b.l; } void add(int p,int d) { c[cn[p]]--; cn[p]+=d; c[cn[p]]++; } void slove(int p,int x) { if(p>=l&&p<=r) { add(a[p],-1); add(x,1); } a[p]=x; } int main() { scanf("%d %d",&n,&qq); //block=sqrt(n); block=pow(n,0.666666); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); num[cnt++]=a[i]; belong[i]=i/block+1; } int T=0,t=0; while(qq--) { int op,L,R; scanf("%d %d %d",&op,&L,&R); if(op==1) { q[++t]=(que){L,R,T,t}; } else { st[++T]=(cha){L,R,a[L]}; num[cnt++]=R; a[L]=R; } } sort(num,num+cnt); sort(q+1,q+t+1,cmp); int sz=unique(num,num+cnt)-num; for(int i=1;i<=n;i++) { a[i]=lower_bound(num,num+sz,a[i])-num; } for(int i=1;i<=T;i++) { st[i].now=lower_bound(num,num+sz,st[i].now)-num; st[i].old=lower_bound(num,num+sz,st[i].old)-num; } for(int i=1;i<=t;i++) { while(T<q[i].tim){slove(st[T+1].p,st[T+1].now);T++;} while(T>q[i].tim){slove(st[T].p,st[T].old);T--;} while(l<q[i].l){add(a[l],-1);l++;} while(l>q[i].l){add(a[l-1],1);l--;} while(r<q[i].r){add(a[r+1],1);r++;} while(r>q[i].r){add(a[r],-1);r--;} while(c[ans])ans++; an[q[i].id]=ans; ans=1; } for(int i=1;i<=t;i++) { printf("%d ",an[i]); } return 0; }