}
```
+下面提供 [【模板】可持久化线段树 2(主席树)](https://www.luogu.com.cn/problem/P3834) 一题使用整体二分的,偏向竞赛风格的写法。
+
+???+note "参考代码"
+ ```cpp
+ #include <bits/stdc++.h>
+ using namespace std;
+ const int N = 200020;
+ const int INF = 1e9;
+ int n, m;
+ int ans[N];
+ // BIT begin
+ int t[N];
+ int a[N];
+ int sum(int p) {
+ int ans = 0;
+ while (p) {
+ ans += t[p];
+ p -= p & (-p);
+ }
+ return ans;
+ }
+ void add(int p, int x) {
+ while (p <= n) {
+ t[p] += x;
+ p += p & (-p);
+ }
+ }
+ // BIT end
+ int tot = 0;
+ struct Query {
+ int l, r, k, id, type; // set values to -1 when they are not used!
+ } q[N * 2], q1[N * 2], q2[N * 2];
+ void solve(int l, int r, int ql, int qr) {
+ if (ql > qr) return;
+ if (l == r) {
+ for (int i = ql; i <= qr; i++)
+ if (q[i].type == 2) ans[q[i].id] = l;
+ return;
+ }
+ int mid = (l + r) / 2, cnt1 = 0, cnt2 = 0;
+ for (int i = ql; i <= qr; i++) {
+ if (q[i].type == 1) {
+ if (q[i].l <= mid) {
+ add(q[i].id, 1);
+ q1[++cnt1] = q[i];
+ } else
+ q2[++cnt2] = q[i];
+ } else {
+ int x = sum(q[i].r) - sum(q[i].l - 1);
+ if (q[i].k <= x)
+ q1[++cnt1] = q[i];
+ else {
+ q[i].k -= x;
+ q2[++cnt2] = q[i];
+ }
+ }
+ }
+ // rollback changes
+ for (int i = 1; i <= cnt1; i++)
+ if (q1[i].type == 1) add(q1[i].id, -1);
+ // move them to the main array
+ for (int i = 1; i <= cnt1; i++) q[i + ql - 1] = q1[i];
+ for (int i = 1; i <= cnt2; i++) q[i + cnt1 + ql - 1] = q2[i];
+ solve(l, mid, ql, cnt1 + ql - 1);
+ solve(mid + 1, r, cnt1 + ql, qr);
+ }
+ pair<int, int> b[N];
+ int toRaw[N];
+ int main() {
+ scanf("%d%d", &n, &m);
+ // read and discrete input data
+ for (int i = 1; i <= n; i++) {
+ int x;
+ scanf("%d", &x);
+ b[i].first = x;
+ b[i].second = i;
+ }
+ sort(b + 1, b + n + 1);
+ int cnt = 0;
+ for (int i = 1; i <= n; i++) {
+ if (b[i].first != b[i - 1].first) cnt++;
+ a[b[i].second] = cnt;
+ toRaw[cnt] = b[i].first;
+ }
+ for (int i = 1; i <= n; i++) {
+ q[++tot] = {a[i], -1, -1, i, 1};
+ }
+ for (int i = 1; i <= m; i++) {
+ int l, r, k;
+ scanf("%d%d%d", &l, &r, &k);
+ q[++tot] = {l, r, k, i, 2};
+ }
+ solve(0, cnt + 1, 1, tot);
+ for (int i = 1; i <= m; i++) printf("%d\n", toRaw[ans[i]]);
+ }
+ ```
### 带修区间第 k 小:整体二分的完整运用
> **题 4** [Dynamic Rankings](http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112) 给定一个数列,要支持单点修改,区间查第 $k$ 小。