http://poj.org/problem?id=2104

题意:给出n个数和m个询问求区间第K小。

思路:以前用主席树做过,这次学整体二分来做。整体二分在yr大佬的指点下,终于大概懂了点了。对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了。

在这题二分可行的答案,根据这个答案,把询问操作丢在左右两个队列里面分别递归继续按这样处理。注释里写的很详细。

 #include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const int N = ;
const int INF = 0x3f3f3f3f;
struct P {
int type, l, r, val, id;
} q[N], lq[N], rq[N];
int ans[N], bit[N], sum[N], gap; int lowbit(int x) { return x & (-x); }
void update(int x, int w) { while(x <= gap) bit[x] += w, x += lowbit(x); }
int query(int x) { int ans = ; while(x) ans += bit[x], x -= lowbit(x); return ans; } void Solve(int lask, int rask, int l, int r) { // 整体二分答案,判断答案是否可行
if(rask < lask || r < l) return ;
if(l == r) // 如果找到合适的答案了,那么在这段区间的查询的全部答案都是属于它
{ for(int i = lask; i <= rask; i++) if(q[i].type == ) ans[q[i].id] = l; return ; }
int mid = (l + r) >> , lcnt = , rcnt = ;
for(int i = lask; i <= rask; i++) { // 遍历这段询问
if(q[i].type == ) { // 如果是插入
if(q[i].val <= mid) { // 因为查询的是第k小,那么就是升序排列的第k个数字
lq[++lcnt] = q[i]; // 如果插入的数比当前枚举的答案小,那么符合条件,在树状数组上插入并丢入左队列
update(q[i].id, );
} else rq[++rcnt] = q[i]; // 插入的数比当前枚举的答案大,对当前枚举的答案无影响,丢入右队列
} else { // 如果是询问
int num = query(q[i].r) - query(q[i].l - ); // 那么查询这段区间有多少个数
if(q[i].val <= num) lq[++lcnt] = q[i]; // 如果这段区间的数字比当前查询的k多,那么说明答案在左边
else { // 否则在右边,在右边的话还要减去左边拥有的
q[i].val -= num;
rq[++rcnt] = q[i];
}
}
}
for(int i = lask; i <= rask; i++) if(q[i].type == && q[i].val <= mid) update(q[i].id, -);
for(int i = ; i <= lcnt; i++) q[i+lask-] = lq[i]; // 重新构造
for(int i = ; i <= rcnt; i++) q[i+lask+lcnt-] = rq[i];
Solve(lask, lask + lcnt - , l, mid); // 分两边递归处理
Solve(lask + lcnt, rask, mid + , r);
} int main() {
int n, m, a, b, c;
scanf("%d%d", &n, &m); gap = n;
for(int i = ; i <= n; i++) {
scanf("%d", &a);
q[i] = (P){, , , a, i};
}
for(int i = ; i <= m; i++) {
scanf("%d%d%d", &a, &b, &c);
q[n+i] = (P){, a, b, c, i};
}
Solve(, n + m, -INF, INF);
for(int i = ; i <= m; i++) printf("%d\n", ans[i]);
return ;
}

POJ 2104:K-th Number(整体二分)的更多相关文章

  1. POJ 2104:K-th Number 整体二分

    感觉整体二分是个很有趣的东西. 在别人的博客上看到一句话 对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了 树套树写了一天还是WA着,调得焦头烂额,所以决定学cd ...

  2. poj 3111 K Best 最大化平均值 二分思想

    poj 3111 K Best 最大化平均值 二分思想 题目链接: http://poj.org/problem?id=3111 思路: 挑战程序竞赛书上讲的很好,下面的解释也基本来源于此书 设定条件 ...

  3. POJ2104 K-th Number [整体二分]

    题目传送门 K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 69053   Accepted: 24 ...

  4. BZOJ 3110: [Zjoi2013]K大数查询 [整体二分]

    有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. N ...

  5. BZOJ3110:[ZJOI2013]K大数查询(整体二分)

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  6. BZOJ 3110 K大数查询 | 整体二分

    BZOJ 3110 K大数查询 题面 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个 ...

  7. BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)

    题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...

  8. 【BZOJ-3110】K大数查询 整体二分 + 线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Sta ...

  9. 静态区间第K小(整体二分、主席树)

    题目链接 题解 主席树入门题 但是这里给出整体二分解法 整体二分顾名思义是把所有操作放在一起二分 想想,如果求\([1-n]\)的第\(k\)小怎么二分求得? 我们可以二分答案\(k\), \(O(n ...

随机推荐

  1. CloudFormation

    亚马逊云服务之CloudFormation   亚马逊的Web Service其实包含了一套云服务.云服务主要分为三种: IaaS: Infrastructure as a service,基础设施即 ...

  2. DropDownList单选与多选下拉框

    一.单选DropDownList传值 1.添加界面的DropDownList显示值问题 (1)在方法内添加ViewData的方法: var ad = new UnitsRepository(); Vi ...

  3. IOS 跳转到系统的url

    About — prefs:root=General&path=AboutAccessibility — prefs:root=General&path=ACCESSIBILITYAi ...

  4. HTTP header 介绍

    HTTP(Hyper Text Transfer Protocol)是超文本传输协议的缩写,它用于传送www方式的数据.HTTP协议采用了请求/响应模型.客服端向服务器发送一个请求,请求头包含请求的方 ...

  5. CSS学习小记

    搜狗主页页面CSS学习小记 1.边框的处理   要形成上图所示的布局效果,即,点选后,导航下面的边框不显示而其他的边框形成平滑的形状.相对于把导航的下面边框取消然后用空白覆盖掉下面搜索栏的边框比较而言 ...

  6. SQL 使用存储过程创建报表的一点体会

    以前创建报表的时候都是采用视图的方式来实现的,通过把关联的表字段选取后形成需要的报表,用起来也比较方便. 最近也尝试用存储过程来做一些开发,确实也方便不少,因为很多逻辑关系都可以灵活的在SQL来实现, ...

  7. 使用HttpURLConnection实现多线程下载

    HttpURLConnection继承了URLConnection,因此也可用于向指定网站发送GET请求.POST请求,而且它在URLConnection基础上提供了如下便捷方法: 实现多线程下载的步 ...

  8. Effective C++ 第二版 1)const和inline 2)iostream

    条款1 尽量用const和inline而不用#define >"尽量用编译器而不用预处理" Ex. #define ASPECT_R 1.653    编译器永远不会看到AS ...

  9. OpenRisc-34-ORPSoC跑eCos实验

    引言 ORPSoC目前支持好几种OS,除了前面一直介绍的linux,还支持eCos,eCos是RTOS,如果你的系统对时间的要求比较高,那eCos会是一个不错的选择. 本小节就简单介绍一下,在ORPS ...

  10. VMware vSphere 服务器虚拟化之二十四 桌面虚拟化之手动池管理物理机

    VMware vSphere 服务器虚拟化之二十四 桌面虚拟化之手动池管理物理机 VMwareView手动池可以管理物理计算机 说明: 环境基于实验二十三 1.准备一台Windows 7的物理计算机名 ...