主席树的大水题
维护每个自然数前一个出现的位置
关于查询(l,r)区间,在第(r)颗主席树查询位置小于(l)的第一个数
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL maxn=1e7+10;
inline LL Read(){
LL x=0,f=1; char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
LL n,m,nod;
LL d_min[maxn],son[maxn][2],a[maxn],root[maxn];
inline void Update(LL now){
LL l=son[now][0],r=son[now][1];
d_min[now]=min(d_min[l],d_min[r]);
}
void Change(LL &now,LL pre,LL l,LL r,LL c,LL val){
now=++nod;
if(l==r){
d_min[now]=val;
return;
}
LL mid=(l+r)>>1;
if(c<=mid){
Change(son[now][0],son[pre][0],l,mid,c,val);
son[now][1]=son[pre][1];
}else{
Change(son[now][1],son[pre][1],mid+1,r,c,val);
son[now][0]=son[pre][0];
}
Update(now);
}
LL Query(LL now,LL c,LL l,LL r){
if(l==r)
return l;
LL mid=(l+r)>>1;
if(d_min[son[now][0]]<c)
return Query(son[now][0],c,l,mid);
else
return Query(son[now][1],c,mid+1,r);
}
int main(){
n=Read(),m=Read();
for(LL i=1;i<=n;++i)
a[i]=Read();
for(LL i=1;i<=n;++i){
if(a[i]<=n)
Change(root[i],root[i-1],0,n,a[i],i);
else
root[i]=root[i-1];
}
while(m--){
LL l=Read(),r=Read();
printf("%lld
",Query(root[r],l,0,n));
}
return 0;
}/*
*/