描述

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

如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

分析

  • 今天终于看懂了一个整体二分的题目. 发现这真是一种很BT的做法.
  • 二分答案区间(L, R), 判断中间值M = L+(R-L)/2. 每次清空线段树(直接在根节点上打删除标记, 不要用memset直接清, 会T..).  线段树维护的是在区间(a, b)中比二分的答案M大的数有多少. 处理在(l, r)中的操作, 如果是插入(a, b, c), 判断c和M的大小, c大于M的话在线段树(a, b)区间打增加标记表示+1, 同时操作类型标记为1, c不大于M操作类型标记为0; 如果是查询(a, b, c)操作, 当在线段树(a, b)区间和大于c则说明比M大的超过k个, 那么答案一定比M大, 操作类型标记为1, 否则标记为0.
  • 将所有标记为0的点去下一层(L, M)继续 (可以直接按类型sort, 也可以借鉴归并排序的思想O(n)的归并), 标记为1的点去(M+1, R)继续二分.
  • 当答案区间(L = R)时, 操作区间所有的查询操作的答案都为L.
  • 另 : 1. 在线段树操作时传入太多参数会严重拖慢效率.
  • 2. 在结构体里定义的宏在外面一样用.
代码
#include #include #include using namespace std;
const int maxn = 50000 + 10;
#define M  (L+((R-L)>>1))
struct SegmentTree {
int y1, y2;
int sumv[maxn<<2], addv[maxn<<2];
bool clr[maxn<<2];
void init() {
sumv[1] = addv[1] = 0;
clr[1] = 1;
}
#define lc (o<<1)
#define rc (o<<1^1)
void update(int o) {
sumv[o] = sumv[lc] + sumv[rc];
}
void pushdown(int o, int L, int R) {
if(clr[o]) {
sumv[lc] = sumv[rc] = addv[lc] = addv[rc] = 0;
clr[lc] = clr[rc] = 1;
clr[o] = 0;
}
if(addv[o]) {
int& x = addv[o];
addv[lc] += x;
addv[rc] += x;
sumv[lc] += (M-L+1) * x;
sumv[rc] += (R-M) * x;
x = 0;
}
}
void modify(int o, int L, int R) {
if(y1 <= L && R <= y2) {
addv[o]++;
sumv[o] += (R-L+1);
} else {
pushdown(o, L, R);
if(y1 <= M) modify(lc, L, M);
if(y2 > M) modify(rc, M+1, R);
update(o);
}
}
int query(int o, int L, int R) {
if(y1 <= L && R <= y2) return sumv[o];
pushdown(o, L, R);
int ret = 0;
if(y1 <= M) ret += query(lc, L, M);
if(y2 > M) ret += query(rc, M+1, R);
return ret;
}
} seg;
struct Node {
int opt, id, l, r, v, k;
bool operator < (const Node& rhs) const {
if(k != rhs.k) return k < rhs.k;
return id < rhs.id;
}
} qst[maxn];
int n, m;
int ans[maxn];
void solve(int L, int R, int l, int r) {
if(l > r) return;
if(L == R) {
for(int i = l; i <= r; i++) {
Node& x = qst[i];
if(x.opt == 2) ans[x.id] = L;
}
return;
}
seg.init();
int t = l-1;
for(int i = l; i <= r; i++) {
Node& x = qst[i];
if(x.opt == 1) {
if(x.v > M) {
seg.y1 = x.l;
seg.y2 = x.r;
seg.modify(1, 1, n);
x.k = 1;
} else {
x.k = 0; t++;
}
} else {
seg.y1 = x.l;
seg.y2 = x.r;
int s = seg.query(1, 1, n);
if(x.v <= s) x.k = 1;
else x.k = 0, t++, x.v -= s;
}
}
sort(qst + l, qst + r + 1);
solve(L, M, l, t);
solve(M+1, R, t+1, r);
}
int main()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
int opt, l, r, v;
scanf("%d %d %d %d", &opt, &l, &r, &v);
qst[i] = (Node) {opt, i, l, r, v};
}
memset(ans, -1, sizeof(ans));
solve(0, n, 1, m);
for(int i = 1; i <= m; i++)
if(ans[i] != -1) printf("%d\n", ans[i]);
return 0;
}

BZOJ-3110-K大数查询-ZJOI2013-整体二分相关推荐

  1. P3332 [ZJOI2013]K大数查询(整体二分做法)

    P3332 [ZJOI2013]K大数查询 题意: 题解: 利用整体二分来做,这个题和P3834 [模板]可持久化线段树 2的区别在于本题的修改是区间修改,所以将里面的树状数组改成线段树就行,区间修改 ...

  2. P3332 [ZJOI2013]K大数查询【整体二分】或【树套树】

    传送门 给定一个长度为NNN的可重集合 支持修改,离线 求区间可重集合的并集第K大 这里介绍两种方法[树套树]和 [整体二分] 这里还有个单点修改,有点类似的 P2617 Dynamic Rankin ...

  3. bzoj 3110: [Zjoi2013]K大数查询(树套树)

    树套树: 本质:一棵树的每个节点套着另一棵树 通常时间复杂度:O(nlog²n) 空间复杂度:因为树的大小是nlogn,而每个节点又有一棵nlogn的树,所以最大空间复杂度为O(n²log²) 但事实 ...

  4. 3110: [Zjoi2013]K大数查询

    3110: [Zjoi2013]K大数查询 https://lydsy.com/JudgeOnline/problem.php?id=3110 分析: 整体二分+线段树. 两种操作:区间加入一个数,区 ...

  5. [ZJJOI2013]K大数查询 整体二分

    [ZJJOI2013]K大数查询 链接 luogu 思路 整体二分. 代码 #include <bits/stdc++.h> #define ll long long using name ...

  6. bzoj3110 [Zjoi2013]K大数查询

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 10703  Solved: 3209 [Submit][ ...

  7. 洛谷 P3332 [ZJOI2013]K大数查询 解题报告

    P3332 [ZJOI2013]K大数查询 题目描述 有\(N\)个位置,\(M\)个操作.操作有两种,每次操作如果是\(\tt{1\ a\ b\ c}\)的形式表示在第\(a\)个位置到第\(b\) ...

  8. BZOJ3110: [Zjoi2013]K大数查询

    BZOJ3110: [Zjoi2013]K大数查询 Description 有N个位置,M个操作. 操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如 ...

  9. [BZOJ3110] [Zjoi2013]K大数查询

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 9208  Solved: 2737 [Submit][S ...

  10. python【蓝桥杯vip练习题库】ALGO-1区间k大数查询

    试题 算法训练 区间k大数查询 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示 ...

最新文章

  1. python绘制雷达图代码实例-PYTHON绘制雷达图代码实例
  2. 10个python使用技巧
  3. 学号20145220《信息安全系统设计基础》第12周学习总结
  4. mysql 添加用户_mysql创建用户与授权
  5. word List 12
  6. Java压缩技术(七) TAR——Commons实现
  7. mpython 直接访问_如何从python代码中直接访问Android的Service
  8. 安全测试===sqlmap(零)转载
  9. mysql怎么设置密码都不正确的一个解决方法
  10. Java虚拟机学习(四)
  11. 什么思维是大数据思维,大数据思维的核心是什么?
  12. 利用ckplayer浏览器在线播放视频并获取视频预览图方法
  13. Java学习笔记Day2:流程控制
  14. span标签的间距问题
  15. 蓝精灵:寻找神秘村Smurfs: The Lost Village迅雷下载
  16. linux vrrp 配置命令,虚拟路由器冗余协议(VRRP)简单实验
  17. 苹果系统中国日历服务器,简单三步,让 iPhone 自带日历 App 显示国家节假日安排...
  18. connect的中文意思是什么_connect是什么意思
  19. 区块链入门教程(6)--配置使用控制台
  20. HiveOnSpark

热门文章

  1. 科大星云诗社动态20201206
  2. <马哲>世界2017-12-27
  3. python3中map函数_python3中map()和reduce()函数
  4. [scala-spark]3. 变量 数据类型 分支与循环
  5. html并排放多张图片时出现分割的白条
  6. foreach形式的for语句
  7. session或者error引起的iframe嵌套问题的解决
  8. 程序员面试系列——有符号数的溢出
  9. MyBatis-Plus 高级功能 —— 乐观锁插件
  10. Java后端返回通用接口设计