时间复杂度 \(O(nlogn)\),建树、查询、修改。
区间第 \(k\) 小值。
https://www.luogu.com.cn/problem/P3834
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
struct PresidentTree{
static constexpr int N = 2e5 + 10;
int cntNodes, root[N];
struct node{
int l, r;
int cnt;
LL sum;
}tr[N * 4 + N * 17];
void modify(int &u, int v, int l, int r, int x){
u = ++ cntNodes;
tr[u] = tr[v];
tr[u].cnt ++ ;
if (l == r) return;
int mid = l + r >> 1;
if (x <= mid) modify(tr[u].l, tr[v].l, l, mid, x);
else modify(tr[u].r, tr[v].r, mid + 1, r, x);
}
int kth(int p, int q, int l, int r, int k){
if (l == r) return l;
int res = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
int mid = l + r >> 1;
if (k <= res) return kth(tr[p].l, tr[q].l, l, mid, k);
else return kth(tr[p].r, tr[q].r, mid + 1, r, k - res);
}
};
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int n, m;
cin >> n >> m;
vector<int> a(n + 1), val;
for (int i = 1; i <= n; i++){
cin >> a[i];
val.push_back(a[i]);
}
sort(val.begin(), val.end());
val.erase(unique(val.begin(), val.end()), val.end());
for (int i = 1; i <= n; i ++ ){
a[i] = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
}
int siz = val.size();
PresidentTree pt;
for (int i = 1; i <= n; i ++ ){
pt.modify(pt.root[i], pt.root[i - 1], 0, siz - 1, a[i]);
}
while (m -- ){
int l, r, k;
cin >> l >> r >> k;
cout << val[pt.kth(pt.root[l - 1], pt.root[r], 0, siz - 1, k)] << "\n";
}
return 0;
}
区间前 k 大值之和。
E题:https://codeforces.com/gym/102770
区间内在 \([1, k]\) 范围内的元素和。
M题:https://ac.nowcoder.com/acm/contest/12548/