主席树(区间第k大值)
#include <bits/stdc++.h> typedef long long ll; using namespace std; const int N=1e5+5; int n, m, k, cnt; int ls[N<<5], rs[N<<5], sum[N<<5], rt[N<<5]; int a[N], b[N]; int build(int l, int r){ int root = ++ cnt; if(l == r) return root; int mid = (l + r) >> 1; ls[root] = build(l, mid); rs[root] = build(mid + 1, r); return root; } int update(int k, int l, int r, int root){ int id = ++ cnt; ls[id] = ls[root]; rs[id] = rs[root]; sum[id] = sum[root] + 1; if(l == r) return id; int mid = (l + r) >> 1; if(k <= mid) ls[id] = update(k, l, mid, ls[id]); if(k > mid) rs[id] = update(k, mid + 1, r, rs[id]); return id; } int query(int k, int u, int v, int l, int r)//查询区间第k小值 { int mid = (l + r) >> 1; int x = sum[ls[v]] - sum[ls[u]]; if(l == r) return l; if(k <= x) return query(k, ls[u], ls[v], l, mid); if(k > x) return query(k - x, rs[u], rs[v], mid + 1, r); } int ask(int k, int u, int v, int l, int r)//查询区间小于等于k的数的个数 { if(k >= b[r]) return sum[v] - sum[u]; if(k < b[l]) return 0; int ans = 0; int mid = (l + r) >> 1; if(k <= b[mid]) ans += ask(k, ls[u], ls[v], l, mid); else { ans += sum[ls[v]] - sum[ls[u]]; ans += ask(k, rs[u], rs[v], mid + 1, r); } return ans; } void init() { memset(sum,0,sizeof sum); cnt=k=0; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int _,n,kk; cin>>_; while(_--) { init(); cin>>n>>kk; for(int i=1;i<=n;i++) { cin>>a[i]; b[i]=a[i]; } sort(b + 1, b + 1 + n); int len = unique(b + 1, b + 1 + n) - b - 1; rt[0] = build(1, len); for(int i = 1 ; i <= n ; ++ i) { int x = lower_bound(b + 1, b + 1 + len, a[i]) - b; rt[i] = update(x, 1, len, rt[i-1]); } ask(i,rt[ln-1],rt[rn],1,len); b[query(l-1, rt[ln-1], rt[rn], 1, len)]; } return 0; }