Rmq Problem/mex BZOJ3339 BZOJ3585
分析:
一开始没看懂题...
后来想用二分答案却不会验证...
之后,想到用主席树来维护...
建一个权值线段树,维护出这个权值以前所有的点最晚在哪里出现...
之后,查一下是不是比查询区间的l断点大...如果小,往左查,如果大,往右查...
附上代码...
#include <cstdio> #include <algorithm> #include <iostream> #include <queue> #include <cmath> #include <cstring> #include <cstdlib> using namespace std; #define N 200005 #define lson l,m,tr[rt].ls #define rson m+1,r,tr[rt].rs struct node { int ls,rs,minn; }tr[N*20]; int a[N],rot[N],n,Q,cnt; void insert(int x,int l,int r,int &rt,int v,int c) { if(!rt)rt=++cnt; if(l==r) { tr[rt].minn=c; return ; } int m=(l+r)>>1; if(m>=v)tr[rt].rs=tr[x].rs,insert(tr[x].ls,lson,v,c); else tr[rt].ls=tr[x].ls,insert(tr[x].rs,rson,v,c); tr[rt].minn=min(tr[tr[rt].ls].minn,tr[tr[rt].rs].minn); } int query(int l,int r,int rt,int k) { if(l==r)return l; int m=(l+r)>>1; if(tr[tr[rt].ls].minn<k)return query(lson,k); else return query(rson,k); } int main() { scanf("%d%d",&n,&Q); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); insert(rot[i-1],0,200000,rot[i],a[i],i); } while(Q--) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",query(0,200000,rot[y],x)); } }