这道题的 comment 里有人说
题目链接
Beautiful problem. There exists solution which run in O(log^3 N), O(log^2 N), and O(log N) per query. Explore them and learn something new!
我学到的第一种应该是最大的那种, 就是构造一个线段树, 其中每个节点都是排序后的对应区间上的数。然后通过二分求第k大
这种只能处理静态。。
const int N = 100005;
int n, m, ai[N];
vector<int> tree[N*4], nodes;
#define lc o<<1
#define rc o<<1|1
void build(int o, int l, int r) {
if ( l == r ) {
int x;
scanf("%d", &x);
tree[o].push_back(x);
} else {
int m = (l + r) >> 1;
build(lc, l, m);
build(rc, m + 1, r);
tree[o].resize(r - l + 1);
merge(tree[lc].begin(), tree[lc].end(),
tree[rc].begin(), tree[rc].end(), tree[o].begin());
}
}
void query(int o, int l, int r, int ql, int qr) {
if ( ql <= l && r <= qr ) {
nodes.push_back(o);
return;
}
int m = (l + r) >> 1;
if ( ql <= m )
query(lc, l, m, ql, qr);
if ( qr > m )
query(rc, m + 1, r, ql, qr);
}
int cnt(int key) {
int ret = 0;
for (int i = 0; i < nodes.size(); ++i) {
const vector<int> &v = tree[nodes[i]];
ret += lower_bound(v.begin(), v.end(), key) - v.begin();
}
return ret;
}
int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
scanf("%d%d", &n, &m);
build(1, 1, n);
vector<int> vals = tree[1];
vals.resize( unique(vals.begin(), vals.end()) - vals.begin() );
rep(ri, 1, m) {
int x, y, k;
scanf("%d%d%d", &x, &y, &k);
int l = 0, r = vals.size(), m;
nodes.clear();
query(1, 1, n, x, y);
// 这里的复杂度
// logn * logn * logn
while ( l < r ) {
m = (l + r) >> 1;
int tmp = cnt(vals[m]);
if ( tmp < k )
l = m + 1;
else
r = m;
}
printf("%d\n", vals[r-1]);
}
return 0;
}