https://cwoj.tk/problempage.php?problem_id=1198
出这道题的目的是学习最基础主席树,对已掌握主席树的选手,完全不需要去看,对完全不会主席树的同学,有学习的价值
稍后可能附上具体思路
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 100010;
int n, m, a[N], tem[N], ntem;
const int M = N * (4 + 17);
int nnod, lid[M], rid[M], Tid[N], val[M];
//build an empty complete tree, of vital importance!
int plant(int l, int r){
int t = ++nnod;
val[t] = 0;
if(l == r) return t;
int mid = (l + r) >> 1;
lid[t] = plant(l, mid);
rid[t] = plant(mid + 1, r);
return t;
}
//build this tree from father tree
int update(int id, int l, int r, int p, int v){
int t = ++nnod;
lid[t] = lid[id], rid[t] = rid[id];
val[t] = val[id] + v;
if(l == r) return t;
int mid = (l + r) >> 1;
if(p <= mid) lid[t] = update(lid[t], l, mid, p, v);
else rid[t] = update(rid[t], mid + 1, r, p, v);
return t;
}
//query k-th element in segment a[l, r]
int queryKth(int Lid, int Rid, int l, int r, int k){
if(l == r) return tem[l];
int mid = (l + r) >> 1;
int lval = val[lid[Rid]] - val[lid[Lid]];//very seay to get wrong!
if(lval >= k) return queryKth(lid[Lid], lid[Rid], l, mid, k);
else return queryKth(rid[Lid], rid[Rid], mid + 1, r, k - lval);
}
int main(){
while(scanf("%d", &n) != EOF){
//read array a
ntem = 0;
for(int i = 1; i <= n; i++){
scanf("%d", a + i);
tem[++ntem] = a[i];
}
//hash: in Chinese "Li San Hua"
sort(tem + 1, tem + 1 + ntem);
ntem = (int)(unique(tem + 1, tem + 1 + ntem) - (tem + 1));
//build an empty complete tree
nnod = 0;
Tid[0] = plant(1, ntem);
//build another n trees
for(int i = 1; i <= n; i++){
int p = (int)(lower_bound(tem + 1, tem + 1 + ntem, a[i]) - tem);
Tid[i] = update(Tid[i-1], 1, ntem, p, +1);
}
//get answers
scanf("%d", &m);
for(int i = 1; i <= m; i++){
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
int ans = queryKth(Tid[l-1], Tid[r], 1, ntem, k);
printf("%d\n", ans);
}
}
return 0;
}