Jzoj3547 MEX
有一个长度为n的数组{a1,a2,...,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。
这是一个经典的主席树的题目,对于每个节点i开一颗线段树存储[1,i]区间内每个数最后出现的位置,那么查找的时候直接再树上类似平衡树找最小即可
#pragma GCC opitmize("O3") #pragma G++ opitmize("O3") #include<stdio.h> #include<string.h> #include<algorithm> #define N 200010 #define M 1000000000 using namespace std; struct tree{ int l,r,v; } s[N*50]; int rt[N],n,m,cnt=0; void insert(int l,int r,int r1,int& r2,int k,int id){ if(!r2) r2=++cnt; if(l==r){ s[r2].v=id; return; } int m=l+r>>1; if(k<=m){ s[r2].r=s[r1].r; insert(l,m,s[r1].l,s[r2].l,k,id); } else { s[r2].l=s[r1].l; insert(m+1,r,s[r1].r,s[r2].r,k,id); } s[r2].v=min(s[s[r2].l].v,s[s[r2].r].v); } int query(int l,int r,int r1,int k){ if(s[r1].v>=k) return M; if(l==r) return l; int m=l+r>>1; if(s[s[r1].l].v<k) return query(l,m,s[r1].l,k); return query(m+1,r,s[r1].r,k); } int main(){ scanf("%d%d",&n,&m); for(int x,i=1;i<=n;++i){ scanf("%d",&x); insert(0,M,rt[i-1],rt[i],x,i); } for(int l,r;m--;){ scanf("%d%d",&l,&r); printf("%d\n",query(0,M,rt[r],l)); } }