http://www.lydsy.com/JudgeOnline/problem.php?id=1901

重新用整体二分写了一下。

整体二分的思想详见论文。

貌似带修区间k大和静态区间k大都是\(O(n\log^2n)\)。

cdq是对时间分治,整体二分是对答案分治。

对于动态区间k大怎么实现我还想了很长时间呢,感觉模板题都想这么长时间。。。

动态区间k大的关键步骤是把修改变成两个操作,删除和插入。

这样在一个分治函数内部就可以扫时间轴然后在特定权值范围内的删除和插入分别在bits上-1和+1。

相比较在线bits套主席树,离线整体二分跑得飞快。

离散化后跑得能快一点,不离散的话时间复杂度就是\(O(n\log n\log 10^9)\),离散的话时间复杂度是\(O(n\log^2n)\)。

#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;
}

【BZOJ 1901】【ZJU 2112】Dynamic Rankings的更多相关文章

  1. 【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题

    达神题解传送门:http://blog.csdn.net/dad3zz/article/details/50638360 说一下我对这个模板的理解: 看到这个方法很容易不知所措,因为动态K值需要套树状 ...

  2. 【bzoj 1901】Zju2112 Dynamic Rankings

    Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是 ...

  3. 【BZOJ 1901】Zju2112 Dynamic Rankings &&【COGS 257】动态排名系统 树状数组套线段树

    外面是树状数组,里面是动态开点线段树,对于查询我们先把有关点找出来,然后一起在线段树上行走,这样就是单个O(log2)的了 #include <cstdio> #include <v ...

  4. 【BZOJ】【1901】【Zju2112】 Dynamic Rankings

    再填个坑. 动态维护区间第K大(带单点修改) 首先裸的区间第K大我们是用的[前缀和]思想,实现O(n)预处理,O(1)找树查询,那么如果是动态的呢?我们可以利用树状数组(BIT)的思想,进行O(log ...

  5. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  6. BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7143  Solved: 2968[Su ...

  7. 【BZOJ】3052: [wc2013]糖果公园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...

  8. 【BZOJ】3319: 黑白树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种: ...

  9. 【BZOJ】3319: 黑白树(并查集+特殊的技巧/-树链剖分+线段树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 以为是模板题就复习了下hld............................. 然后n ...

随机推荐

  1. perl中的lock

    #!/usr/bin/env perl -w use strict; use threads; use threads::shared; ; print "count的起始值为:$count ...

  2. [Leetcode Week15]Populating Next Right Pointers in Each Node II

    Populating Next Right Pointers in Each Node II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/popul ...

  3. python基础===【爬虫】爬虫糗事百科首页图片代码

    import requests import re import urllib.request def getHtml(url): page = requests.get(url) html = pa ...

  4. UNIX v6

    UNIX v6 http://download.csdn.net/download/u013896535/9106775 https://github.com/chromium/mini_chromi ...

  5. HDU 4305 Lightning Matrix Tree定理

    题目链接:https://vjudge.net/problem/HDU-4305 解法:首先是根据两点的距离不大于R,而且中间没有点建立一个图.之后就是求生成树计数了. Matrix-Tree定理(K ...

  6. 批量导出文件名 另存为bat文件

    @echo offdir /b *.* > 导出的文件名.txtexit

  7. jQuery使用blur()方法触发两次的解决方法

    在项目中的textarea在是去焦点时对文本内容进行验证,这时候使用了blur方法,但是实现时blur的回调函数执行了两次,这里我也不知道为什么,然后就尝试先解除blur事件绑定,然后再绑定blur事 ...

  8. (转载)IntelliJ IDEA 自动导入包 快捷方式

    原文地址:IntelliJ IDEA 自动导入包 快捷方式 idea可以自动优化导入包,但是有多个同名的类调用不同的包,必须自己手动Alt+Enter设置 设置idea导入包 勾选标注 1 选项,In ...

  9. Jump Game I&&II——入门级贪心算法

    Jump Game I Given an array of non-negative integers, you are initially positioned at the first index ...

  10. 解决错误:此用户名包含无效字符,请输入有效的用户名。wordpress不能注册中文用户名的问题

    wordpress在默认情况下不支持中文用户名,就是在后台添加用户的时候,如果用户名包含中文,则显示”错误:此用户名包含无效字符,请输入有效的用户名.”如何解决这个问题呢? 不用插件的话就需要修改一个 ...