-整体二分-树状数组- [洛谷 P2617]Dynamic Rankings

题目描述

Link

Solution

这题我们用整体二分。

为什么不用主席树套树状数组呢?最主要的原因就是我不会。因为主席树再套一个树状数组空间开销有些大,故不用主席树套树状数组虽然我写的整体二分空间占用也小不到那里去

我们只需要把修改操作拆成删除、赋值两个操作就可以了,剩下的就是普通的整体二分查第K大了。

而且别忘了用树状数组维护修改操作。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 200010
#define INF 1000000000
struct rec {
int op, x, y, z;
} q[MAXN << 2], lq[MAXN << 2], rq[MAXN << 2];
int n, m, t, c[MAXN], ans[MAXN], id, a[MAXN];
int ask(int x) {
int y = 0;
for (; x; x -= x & -x) y += c[x];
return y;
}
void change(int x, int y) {
for (; x <= n; x += x & -x) c[x] += y;
}
void solve(int lval, int rval, int st, int ed) {
if (st > ed) return;
if (lval == rval) {
for (int i = st; i <= ed; i++) {
if (q[i].op > 0) ans[q[i].op] = lval;
}
return;
}
int mid = (lval + rval) >> 1;
int lt = 0, rt = 0;
for (int i = st; i <= ed; i++) {
if (q[i].op == 0) {
if (q[i].y <= mid) change(q[i].x, 1), lq[++lt] = q[i];
else rq[++rt] = q[i];
}
if (q[i].op == -1) {
if (q[i].y <= mid) change(q[i].x, -1), lq[++lt] = q[i];
else rq[++rt] = q[i];
}
if (q[i].op > 0){
int cnt = ask(q[i].y) - ask(q[i].x - 1);
if (cnt >= q[i].z) lq[++lt] = q[i];
else q[i].z -= cnt, rq[++rt] = q[i];
}
}
for (int i = ed; i >= st; i--) {
if (q[i].op == 0 && q[i].y <= mid) change(q[i].x, -1);
if (q[i].op == -1 && q[i].y <= mid) change(q[i].x, 1);
}
for (int i = 1; i <= lt; i++) q[st + i - 1] = lq[i];
for (int i = 1; i <= rt; i++) q[st + lt + i - 1] = rq[i];
solve(lval, mid, st, st + lt - 1);
solve(mid + 1, rval, st + lt, ed);
}
int l, r, k;
char op[2];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
int val;
scanf("%d", &val);
a[i] = val;
q[++t].op = 0, q[t].x = i, q[t].y = val;
}
for (int i = 1; i <= m; i++) {
scanf("%s%d%d", op, &l, &r);
if (op[0] == 'Q') {
scanf("%d", &k);
q[++t].op = ++id, q[t].x = l, q[t].y = r, q[t].z = k;
}
else {
q[++t].op = -1, q[t].x = l, q[t].y = a[l];
q[++t].op = 0, q[t].x = l, q[t].y = r;
a[l] = r;
}
}
solve(-INF, INF, 1, t);
for (int i = 1; i <= id; i++) {
printf("%d\n", ans[i]);
}
return 0;
}
文章作者: RiverFun
文章链接: https://stevebraveman.github.io/blog/2019/04/15/74/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 RiverFun

评论