主席树里每个值的位置存当前该值出现的最右位置。
如果root[r]的前缀主席树中,某值最右位置大于等于l,说明该值出现在了l,r中。
所以主席树维护区间最小值,如果左半值域的最小值<l,则说明左半值域有值未在l,r出现,则查询左子树;否则查询右子树。
#include<cstdio> #include<algorithm> using namespace std; #define N 1000010 struct Node{int v,lc,rc;}T[N*22]; int root[N],e; void Insert(int pre,int cur,int p,int v,int l,int r) { if(l==r) { T[cur].v=v; return; } int m=(l+r>>1); if(p<=m) { T[cur].lc=++e; T[cur].rc=T[pre].rc; Insert(T[pre].lc,T[cur].lc,p,v,l,m); } else { T[cur].rc=++e; T[cur].lc=T[pre].lc; Insert(T[pre].rc,T[cur].rc,p,v,m+1,r); } T[cur].v=min(T[T[cur].lc].v,T[T[cur].rc].v); } int Goal; int Query(int R,int l,int r) { if(l==r) return l; int m=(l+r>>1); if(T[T[R].lc].v<Goal) return Query(T[R].lc,l,m); else return Query(T[R].rc,m+1,r); } int n,m,a[N]; int main() { int x,y; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&x); root[i]=++e; Insert(root[i-1],root[i],x+1,i,1,1000001); } scanf("%d",&m); for(;m;--m) { scanf("%d%d",&x,&y); Goal=x; printf("%d\n",Query(root[y],1,1000001)-1); } return 0; }
时间: 2024-10-15 00:16:18