【BZOJ 1901】【ZJU 2112】Dynamic Rankings
http://www.lydsy.com/JudgeOnline/problem.php?id=1901
重新用整体二分写了一下。
整体二分的思想详见论文。
貌似带修区间k大和静态区间k大都是。
cdq是对时间分治,整体二分是对答案分治。
对于动态区间k大怎么实现我还想了很长时间呢,感觉模板题都想这么长时间。。。
动态区间k大的关键步骤是把修改变成两个操作,删除和插入。
这样在一个分治函数内部就可以扫时间轴然后在特定权值范围内的删除和插入分别在bits上-1和+1。
相比较在线bits套主席树,离线整体二分跑得飞快。
离散化后跑得能快一点,不离散的话时间复杂度就是,离散的话时间复杂度是。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 10003;
struct node {int x, y, k, op, id;} B[N << 2], q1[N << 2], q2[N << 2];
int tot = 0, a[N], n, m, bits[N << 1], top = 0, H[N << 1], cnt = 0;
int ans[N], id[N << 2], anstot = 0, que[N << 1], q1len, q2len;
void add(int x, int flag) {for (; x <= n; x += (x & (-x))) bits[x] += flag;}
int sum(int x) {int ret = 0; for (; x; x -= (x & (-x))) ret += bits[x]; return ret;}
void solve(int p, int q, int l, int r) {
if (p > q) return;
if (l == r) {
for (int i = p; i <= q; ++i)
if (B[i].op == 3)
ans[B[i].id] = l;
return;
}
int mid = (l + r) >> 1;
for (int i = p; i <= q; ++i) {
if (B[i].op != 3) {
if (B[i].y <= mid)
add(B[i].x, B[i].op);
}
else que[i] = sum(B[i].y) - sum(B[i].x - 1);
}
for (int i = p; i <= q; ++i)
if (B[i].op != 3 && B[i].y <= mid) add(B[i].x, -B[i].op);
q1len = q2len = 0;
for (int i = p; i <= q; ++i)
if (B[i].op != 3) {
if (B[i].y > mid) q2[++q2len] = B[i];
else q1[++q1len] = B[i];
} else {
if (que[i] >= B[i].k) q1[++q1len] = B[i];
else B[i].k -= que[i], q2[++q2len] = B[i];
}
int tmp = p - 1;
for (int i = 1; i <= q1len; ++i)
B[++tmp] = q1[i];
for (int i = 1; i <= q2len; ++i)
B[++tmp] = q2[i];
tmp = p + q1len - 1;
solve(p, tmp, l, mid);
solve(tmp + 1, q, mid + 1, r);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
B[++tot] = (node) {i, a[i], 0, 1, 0};
H[++cnt] = a[i];
}
int x, y, k;
char c[2];
for (int i = 1; i <= m; ++i) {
scanf("%s", c);
if (c[0] == 'Q') {
scanf("%d%d%d", &x, &y, &k);
B[++tot] = (node) {x, y, k, 3, ++anstot};
} else {
scanf("%d%d", &x, &y);
B[++tot] = (node) {x, a[x], 0, -1, 0};
B[++tot] = (node) {x, y, 0, 1, 0};
H[++cnt] = (a[x] = y);
}
}
stable_sort(H + 1, H + cnt + 1);
cnt = unique(H + 1, H + cnt + 1) - H;
for (int i = 1; i <= tot; ++i)
if (B[i].op != 3)
B[i].y = lower_bound(H + 1, H + cnt, B[i].y) - H;
solve(1, tot, 1, cnt - 1);
for (int i = 1; i <= anstot; ++i) printf("%d\n", H[ans[i]]);
return 0;
}
NOI 2017 Bless All
分类:
其他-整体二分
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了