题目:单点更新查询区间第k大

按照主席树的思想,要主席树套树状数组。即按照每个节点建立主席树,然后利用树状数组的方法来更新维护前缀和。然而,这样的做法在实际中并不能AC,原因即卡空间。

因此我们采用一种叫做整体二分的方法。

说一下具体做法:

首先要离线处理

我们把原数列也当成单点更新的操作,而更改值我们则看成两个操作,第一个是删掉原来位置的值,第二个是把新的值放置在这个位置,这样一来我们就可以得到最长n*3的操作序列。

然后就是我们的整体二分步骤了,首先我们对答案进行二分,这时我们会获得一个mid值。此时对于某个询问,如果我们发现在区间内不大于mid的值的个数少于k的时候,我们显然要在比mid大的区间进行二分查找答案,然而我们这次的查找怎么办呢?答案就是记录下来。我们发现在比mid大的区间查找答案的时候,我们之前这次的查找必然也会对下次的查找做出同样的贡献,因此我们只要把这次查找的结果存下来,下次就可以避免重复查找。而另外一种情况,就不大于mid的值的个数大于等于k的时候,我们显然就需要在比mid小的区间进行查找啦,此时我们之前的查找信息只能作废。

据说整体二分的时间复杂度和询问的长度是线性相关的,然而我却认为是nlogn的,这里还不太懂,希望有大神解答...

ZOJ 2112 Dynamic Rankings链接如下:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112

此题卡主席树的空间,但是用此代码结果如下:

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 1000000000 using namespace std; int T, n, m, tot, cnt;
int a[50010], ans[10010], tree[50010], cur[70010];
char str[5]; void updata(int pos, int val) {
while (pos <= n) {
tree[pos] += val;
pos += pos & (-pos);
}
} int read(int pos) {
int tmp = 0;
while (pos > 0) {
tmp += tree[pos];
pos -= pos & (-pos);
}
return tmp;
} struct N {
int l, r, k, id, cur, tp;
N() {}
N(int _l, int _r, int _k, int _id, int _cur, int _tp):
l(_l), r(_r), k(_k), id(_id), cur(_cur), tp(_tp) {}
};
N q[70010], q1[70010], q2[70010]; void ask(int fro, int las, int l, int r) {
if (fro > las) return ;
if (l == r) {
for (int i = fro; i <= las; i++) {
if (q[i].tp == 3) ans[q[i].id] = l;
}
return ;
}
int mid = (l + r) / 2;
for (int i = fro; i <= las; i++) {
if (q[i].tp == 1 && q[i].k <= mid) updata(q[i].l, 1);
else if (q[i].tp == 2 && q[i].k <= mid) updata(q[i].l, -1);
else if (q[i].tp == 3) cur[i] = read(q[i].r) - read(q[i].l - 1);
}
for (int i = fro; i <= las; i++) {
if (q[i].tp == 1 && q[i].k <= mid) updata(q[i].l, -1);
else if (q[i].tp == 2 && q[i].k <= mid) updata(q[i].l, 1);
}
int t1 = 0, t2 = 0;
for (int i = fro; i <= las; i++) {
if (q[i].tp == 3) {
if (q[i].cur + cur[i] >= q[i].k) {
q1[t1++] = q[i];
}
else {
q[i].cur += cur[i];
q2[t2++] = q[i];
}
}
else {
if (q[i].k <= mid) q1[t1++] = q[i];
else q2[t2++] = q[i];
}
}
for (int i = 0; i < t1; i++) q[fro + i] = q1[i];
for (int i = 0; i < t2; i++) q[fro + t1 + i] = q2[i];
ask(fro, fro + t1 - 1, l, mid);
ask(fro + t1, las, mid + 1, r);
} int main() {
//freopen("in.in", "r", stdin);
//freopen("out.out", "w", stdout);
scanf("%d", &T);
while (T--) {
memset(tree, 0, sizeof(tree));
scanf("%d %d", &n, &m);
tot = cnt = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
q[tot++] = N(i, i, a[i], 0, 0, 1);
}
int l, r, k;
for (int i = 0; i < m; i++) {
scanf("%s", str);
if (str[0] == 'Q') {
scanf("%d %d %d", &l, &r, &k);
q[tot++] = N(l, r, k, ++cnt, 0, 3);
}
else {
scanf("%d %d", &l, &k);
q[tot++] = N(l, l, a[l], 0, 0, 2);
q[tot++] = N(l, l, k, 0, 0, 1);
a[l] = k;
}
}
//printf("tot = %d cnt = %d\n", tot, cnt);
ask(0, tot - 1, 0, inf);
for (int i = 1; i <= cnt; i++)
printf("%d\n", ans[i]);
}
return 0;
}

最后,为神马csdn没有发首页的功能了呢,酱紫我的博客谁来看啊

整体二分&cdq分治 ZOJ 2112 Dynamic Rankings的更多相关文章

  1. 整体二分(SP3946 K-th Number ZOJ 2112 Dynamic Rankings)

    SP3946 K-th Number (/2和>>1不一样!!) #include <algorithm> #include <bitset> #include & ...

  2. 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )

    在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...

  3. ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)

    题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...

  4. ZOJ 2112 Dynamic Rankings(带修改的区间第K大,分块+二分搜索+二分答案)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  5. 高级数据结构(树状数组套主席树):ZOJ 2112 Dynamic Rankings

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  6. BZOJ 1901 洛谷 P2617 ZOJ 2112 Dynamic Rankings

    以下时空限制来自zoj Time limit 10000 ms Memory limit 32768 kB OS Linux Source Online Contest of Christopher' ...

  7. ZOJ 2112 Dynamic Rankings(主席树の动态kth)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 The Company Dynamic Rankings ...

  8. zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap

    Dynamic Rankings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/show ...

  9. ZOJ -2112 Dynamic Rankings 主席树 待修改的区间第K大

    Dynamic Rankings 带修改的区间第K大其实就是先和静态区间第K大的操作一样.先建立一颗主席树, 然后再在树状数组的每一个节点开线段树(其实也是主席树,共用节点), 每次修改的时候都按照树 ...

随机推荐

  1. 算法之美&数据结构与算法复习

    1.归并两个有序链表(归并排序) 2.最小路径和--BP解法 3.计算int sqrt(x)--二分解法 4.趣味面试题 5.跳步游戏(Jump_Game)--后向回溯算法 6.Excel列号转十进制 ...

  2. FTP-学习笔记(1)

    1.简单的SFTP.FTP文件上传下载 SftpTools.java package com.lfy.mian; import com.jcraft.jsch.*; import java.io.Fi ...

  3. while与格式化的练习

    练习 判断下列逻辑语句的结果,一定要自己先分析 1)1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 2)n ...

  4. 手写spring事务框架, 揭秘AOP实现原理。

    AOP面向切面编程:主要是通过切面类来提高代码的复用,降低业务代码的耦合性,从而提高开发效率.主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等. AOP实现原理:aop是通过cgli ...

  5. 封装class类--分割类名后

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. Java基础学习(1)

    Java基础知识 Java平台 1995年由Sun公司创建 Java的体系结构 JVM Java Virtue Machine Java代码的执行顺序 JDK Java Development Kit ...

  7. Apache 的 httpd-mpm.conf 文件详解

    #prefork 多路处理模块 <IfModule mpm_prefork_module> StartServers              5   #设置服务器启动时建立的子进程数量, ...

  8. 009-流程控制 for 语句

    流程控制 for 语句 ##################### 语法一 ################################# #!/bin/bash do echo $i done ...

  9. VB TreeView控件使用详解(有趣的示例)

    第一小时:学习直接用代码将数据填充到树控件中. 为什么要先学习直接用代码将数据填充到树控件中?因为这种方法是最简单的,代码也最容易理解,学习树控件,先将这个学会,已经掌握了一半,所以先不要急着想怎么将 ...

  10. 最佳实践:深度学习用于自然语言处理(Deep Learning for NLP Best Practices) - 阅读笔记

    https://www.wxnmh.com/thread-1528249.htm https://www.wxnmh.com/thread-1528251.htm https://www.wxnmh. ...