回顾一下可持久化线段树。
这题是经典的查询静态区间第k小。
对于主席树,可以将每个区间位置,看成第i个历史版本,然后对每个点去维护一棵树。
然后对于第i个点维护的x位置,存的值是1~i的x的前缀和。
查询的时候,比较下前缀和左边是否满足即可。
注意换到右边时,需要减去左区间个数,保证相对第k小。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<string,int> pii; const int N = 2e5+5; const int M = 1e5+5; const LL Mod = 199999; #define rg register #define pi acos(-1) #define INF 1e9 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ 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<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; void FRE(){/*freopen("data1.in","r",stdin); freopen("data1.out","w",stdout);*/} int n,m,rt[N*20],top = 0; LL a[N],b[N],mp[N]; struct Node{int L,r;LL sum;}node[N*20]; int build(int L,int r) { int idx = ++top; node[idx].sum = 0; if(L == r) return idx; int mid = (L+r)>>1; node[idx].L = build(L,mid); node[idx].r = build(mid+1,r); return idx; } void Pushup(int idx) { node[idx].sum = node[node[idx].L].sum + node[node[idx].r].sum; } int update(int x,int L,int r,int pos) { int idx = ++top; node[idx] = node[x]; if(L == r){node[idx].sum++;return idx;} int mid = (L+r)>>1; if(mid >= pos) node[idx].L = update(node[x].L,L,mid,pos); else node[idx].r = update(node[x].r,mid+1,r,pos); Pushup(idx); return idx; } int query(int lidx,int ridx,int L,int r,int k) { if(L == r) return L; int mid = (L+r)>>1; int Lsum = node[node[ridx].L].sum-node[node[lidx].L].sum; if(Lsum >= k) return query(node[lidx].L,node[ridx].L,L,mid,k); else return query(node[lidx].r,node[ridx].r,mid+1,r,k-Lsum); } int main() { n = read(),m = read(); for(rg int i = 1;i <= n;++i) a[i] = read(),b[i] = a[i]; sort(a+1,a+n+1); int len = unique(a+1,a+n+1)-a-1; for(rg int i = 1;i <= n;++i) { int pos = lower_bound(a+1,a+len+1,b[i])-a; mp[pos] = b[i]; b[i] = pos; } rt[0] = build(1,len); for(rg int i = 1;i <= n;++i) rt[i] = update(rt[i-1],1,len,b[i]); while(m--) { int L,r,k; L = read(),r = read(),k = read(); int ans = query(rt[L-1],rt[r],1,len,k); printf("%d ",mp[ans]); } system("pause"); }