嘟嘟嘟




整体二分是一个好东西。

理解起来还行。




首先,需要牢记的是,我们二分的是答案,也就是在值域上二分,同时把操作分到左右区间中(所以操作不是均分的)。

然后我就懒得讲了……

李煜东的《算法竞赛进阶指南》第二版中讲的特别好,有兴趣的OIer可以拿来读读。




这里贴一个板儿。

突然想说一嘴:这道题我们应该保证所有修改(赋值)操作在询问操作之前。虽然代码中没有明显的排序,但是因为读入的时候就先把赋值操作放进操作队列里了,所以二分的每一层,询问区间中一定先是修改,再是询问。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cmath>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #include<cctype>
  8. #include<vector>
  9. #include<stack>
  10. #include<queue>
  11. using namespace std;
  12. #define enter puts("")
  13. #define space putchar(' ')
  14. #define Mem(a, x) memset(a, x, sizeof(a))
  15. #define rg register
  16. typedef long long ll;
  17. typedef double db;
  18. const int INF = 0x3f3f3f3f;
  19. const int Max = 1e9;
  20. const db eps = 1e-8;
  21. const int maxn = 1e5 + 5;
  22. inline ll read()
  23. {
  24. ll ans = 0;
  25. char ch = getchar(), last = ' ';
  26. while(!isdigit(ch)) last = ch, ch = getchar();
  27. while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  28. if(last == '-') ans = -ans;
  29. return ans;
  30. }
  31. inline void write(ll x)
  32. {
  33. if(x < 0) x = -x, putchar('-');
  34. if(x >= 10) write(x / 10);
  35. putchar(x % 10 + '0');
  36. }
  37. int n, m, cnt = 0;
  38. struct Node
  39. {
  40. int x, y, k, id;
  41. }t[maxn << 1], tl[maxn << 1], tr[maxn << 1];
  42. int ans[maxn];
  43. int c[maxn];
  44. int lowbit(int x) {return x & -x;}
  45. void clear(int pos)
  46. {
  47. for(; pos <= n; pos += lowbit(pos))
  48. if(c[pos]) c[pos] = 0;
  49. else return;
  50. }
  51. void update(int pos, int d)
  52. {
  53. for(; pos <= n; pos += lowbit(pos)) c[pos] += d;
  54. }
  55. int query(int pos)
  56. {
  57. int ret = 0;
  58. for(; pos; pos -= lowbit(pos)) ret += c[pos];
  59. return ret;
  60. }
  61. void solve(int l, int r, int ql, int qr)
  62. {
  63. if(ql > qr) return;
  64. if(l == r)
  65. {
  66. for(int i = ql; i <= qr; ++i)
  67. if(t[i].id) ans[t[i].id] = l;
  68. return;
  69. }
  70. int mid = (l + r) >> 1;
  71. int id1 = 0, id2 = 0;
  72. for(int i = ql; i <= qr; ++i)
  73. {
  74. if(!t[i].id)
  75. {
  76. if(t[i].k <= mid) update(t[i].x, 1), tl[++id1] = t[i];
  77. else tr[++id2] = t[i];
  78. }
  79. else
  80. {
  81. int sum = query(t[i].y) - query(t[i].x - 1);
  82. if(sum >= t[i].k) tl[++id1] = t[i];
  83. else t[i].k -= sum, tr[++id2] = t[i];
  84. }
  85. }
  86. for(int i = ql; i <= qr; ++i) if(!t[i].id && t[i].k <= mid) clear(t[i].x);
  87. for(int i = 1; i <= id1; ++i) t[ql + i - 1] = tl[i];
  88. for(int i = 1; i <= id2; ++i) t[ql + id1 + i - 1] = tr[i];
  89. solve(l, mid, ql, ql + id1 - 1);
  90. solve(mid + 1, r, ql + id1, qr);
  91. }
  92. int main()
  93. {
  94. n = read(); m = read();
  95. for(int i = 1; i <= n; ++i) t[++cnt].x = i, t[cnt].k = read(), t[cnt].id = 0;
  96. for(int i = 1; i <= m; ++i)
  97. t[++cnt].x = read(), t[cnt].y = read(), t[cnt].k = read(), t[cnt].id = i;
  98. solve(-Max, Max, 1, cnt);
  99. for(int i = 1; i <= m; ++i) write(ans[i]), enter;
  100. return 0;
  101. }

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

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

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

  2. POJ2104 K-th Number(整体二分)

    题解 又一次做这个题上一次用的是线段树上二分.这次用的是整体二分.结果: (第一个是整体二分) 整体二分就是对于所有查询都二分一个值.然后根据能不能成立把询问修改分成两部分,然后第二部分继承第一部分的 ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. ZOJ 1112 Dynamic Rankings【动态区间第K大,整体二分】

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112 题意: 求动态区间第K大. 分析: 把修改操作看成删除与增加 ...

  10. [ZJOI2013]K大数查询——整体二分

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

随机推荐

  1. 微信支付 统一下单 字段 body 为中文时 报【签名错误】解决方案(C# SDK)

    方案一 如果你是从微信支付官网下载的 .NET C#[微信支付]API对应的SDK 调用示例 查看源码,会发现这个SDK中的 WxPayData 的类的 CalcHMACSHA256Hash 签名方法 ...

  2. 联想拯救者ISK代开BIOS的方法

    按f几都没用,摁fn+f几也不会有用,ISK需要使用物理疗法

  3. SQL 拼接多个字段的值&一个字段多条记录的拼接

    如student表: studentID studentName studentScore 01 Alice 90 02 Bill 95 03 Cindy 100 一.拼接多个字段的值 select ...

  4. centos7配置java环境

    首先自行下载jdk的tar.gz的包,上传至相应服务器目录下,比如我的是:/usr/java下,然后解压缩,之后进行如下操作: 注意要修改/etc/profile文件,在末尾添加内容: export ...

  5. 【Java并发编程】8、各种锁的概念

    持续更新中... 共享锁(S锁):如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁,直到已释放所有共享锁.获准共享锁的事务只能读数据,不能修改数据. 排他锁(X锁):如果事务 ...

  6. 测试单元测试完毕关闭jvm

    今天一天都在纠结Netty中的服务器端究竟是如何实现自动关闭的, 吃完晚饭才发现原来不是netty关闭,是测试单元关闭的...

  7. 【JavaFx教程】第一部分:Scene Builder

    第一部分的主题 开始了解 JavaFX . 创建并运行一个 JavaFX 项目. 使用 Scene Builder 来设计用户界面. 使用 模型 - 视图 - 控制器(MVC)模式 构造基础的应用. ...

  8. ThinkPHP5微信扫码支付

    1.把微信官网下载的demo放在根目录/vendor/目录下,这里我的是/vendor/wxpay_pc目录 2.把cert里面的文件替换成自己项目的证书(登陆微信商户平台,账户中心,API安全下载) ...

  9. JavaSE——线程调度

    线程调度: 按照特定机制为线程分配cpu的使用权. 线程调度模型: 分时调度 所有线程轮流获得cpu的使用权,平均分配每个线程占用的cpu的时间片. 抢占时调度(java虚拟机) 可运行池中优先级高的 ...

  10. FineReport连接多维数据库示例及操作

    1. 描述 FineReport连接多维数据库,首先要通过数据连接将多维数据库与FineReport连接起来,然后在数据连接的基础上新建多维数据库XMLA数据集,用于模板设计. 2.XMLA数据连接 ...