1. 程式人生 > >BZOJ 3585: mex【莫隊+樹狀陣列】

BZOJ 3585: mex【莫隊+樹狀陣列】

3585: mex

【題目描述】
傳送門

【題解】

其實和BZOJ3339一模一樣,當Ai>n時這個Ai對答案沒有影響,這是肯定的,那麼讀入時處理一下就可以了。

程式碼如下

#pragma GCC optimize(2)
#include<cmath>
#include<cstdio>
#include<cctype>
#include<algorithm>
#define MAXN 200005
using namespace std;
int n,q,K,tot,a[MAXN],f[MAXN],hsh[MAXN],Ans[MAXN];
struct
xcw{ int L,R,id; bool operator <(const xcw b)const{return (L/K<b.L/K)||(L/K==b.L/K)&&(R<b.R);} }Q[MAXN]; int read(){ int ret=0;bool f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-'); for(; isdigit(ch);ch=getchar()) ret=(ret<<3)+(ret<<1)+ch-48
; return f?ret:-ret; } void put(int x,int p){for(;x<=tot;x+=x&-x) f[x]+=p;} int get(int x){ int Sum=0; for(;x;x-=x&-x) Sum+=f[x]; return Sum; } void Del(int x){ hsh[a[x]]--; if(hsh[a[x]]==0) put(a[x],-1); } void Add(int x){ if(hsh[a[x]]==0) put(a[x],1); hsh[a[x]]++; } int
Fnd(){ int Ret; if(tot==get(tot)) return tot+1; for(int L=1,R=tot,mid=(R+L)>>1;L<=R;mid=(R+L)>>1) if(mid==get(mid)) L=mid+1;else Ret=mid,R=mid-1; return Ret; } int main(){ #ifndef ONLINE_JUDGE freopen("prob.in","r",stdin); freopen("prob.out","w",stdout); #endif n=read(),q=read();K=sqrt(n); for(int i=1;i<=n;i++) a[i]=read()+1,a[i]=(a[i]>200001?200002:a[i]),tot=max(a[i],tot); for(int i=1;i<=q;i++) Q[i]=(xcw){read(),read(),i}; sort(Q+1,Q+1+q); int L=1,R=0; for(int i=1;i<=q;i++){ while(L<Q[i].L&&L<=n) Del(L++); while(L>Q[i].L&&L>2) Add(--L); while(R<Q[i].R&&R<n) Add(++R); while(R>Q[i].R&&R>0) Del(R--); Ans[Q[i].id]=Fnd()-1; } for(int i=1;i<=q;i++) printf("%d\n",Ans[i]); return 0; }