P3332 [ZJOI2013] K大数查询 题解

news/2025/3/15 21:47:54/文章来源:https://www.cnblogs.com/Scarab/p/18774212

Description

你需要维护 \(n\) 个可重整数集,集合的编号从 \(1\)\(n\)
这些集合初始都是空集,有 \(m\) 个操作:

  • 1 l r c:表示将 \(c\) 加入到编号在 \([l,r]\) 内的集合中
  • 2 l r c:表示查询编号在 \([l,r]\) 内的集合的并集中,第 \(c\) 大的数是多少。

注意可重集的并是不去除重复元素的,如 \(\{1,1,4\}\cup\{5,1,4\}=\{1,1,4,5,1,4\}\)

\(1 \le n,m \le 5\times 10^4\)

Solution

这里考虑一个在线做法。

首先显然需要用到树套树。由于树套树不能下传标记,所以考虑标记永久化。

具体地,对于这 \(n\) 个可重集维护一颗线段树,在线段树上的每个节点 \([l,r]\) 都维护一个值域线段树,表示在 \([l,r]\) 上每个修改的数打的标记的次数。

那么可以得到一个做法:修改时先在修改区间 \([l,r]\) 所有线段树每个分拆区间上打一次标记。查询时则把询问区间 \([L,R]\) 的所有分拆区间的祖先节点(包括自己) \([l_0,r_0]\) 加入 vector,权值为 \(\min(R,r_0)-\max(L,l_0)+1\),然后在这 \(O(\log n)\) 个值域线段树上二分。

但是这么做是不对的,因为询问时的分拆区间 \([l_0,r_0]\) 的子树内(去除自己)的标记是没有算到的,而这些没有算到的标记的权值均为其所在节点的区间长度,所以还需要维护第二个树套树,表示每个节点 \([l,r]\) 子树内的标记对 \([l,r]\) 的贡献,这个在修改时维护即可。

具体见代码。

时间复杂度:\(O(m\log^2n)\)

Code

#include <bits/stdc++.h>// #define int int64_tconst int kMaxN = 5e4 + 5, kMaxT = 2e7 + 5;struct Node {int ls, rs, cnt;
} t[kMaxT];int n, m, sgt_cnt;
int rt1[kMaxN * 4], rt2[kMaxN * 4];void update(int &x, int l, int r, int ql, int v) {if (!x) x = ++sgt_cnt;t[x].cnt += v;if (l == r) return;int mid = (l + r) >> 1;if (ql <= mid) update(t[x].ls, l, mid, ql, v);else update(t[x].rs, mid + 1, r, ql, v);
}void update_arr(int x, int l, int r, int ql, int qr, int c) {if (l > qr || r < ql) return;if (l >= ql && r <= qr) {update(rt1[x], -n, n, c, 1);return;}update(rt2[x], -n, n, c, std::min(r, qr) - std::max(l, ql) + 1);int mid = (l + r) >> 1;update_arr(x << 1, l, mid, ql, qr, c), update_arr(x << 1 | 1, mid + 1, r, ql, qr, c);
}void getpos(int x, int l, int r, int ql, int qr, std::vector<std::pair<int, int>> &vec) {if (l > qr || r < ql) return;if (rt1[x]) vec.emplace_back(rt1[x], std::min(r, qr) - std::max(l, ql) + 1);if (l >= ql && r <= qr) {if (rt2[x]) vec.emplace_back(rt2[x], 1);return;}int mid = (l + r) >> 1;getpos(x << 1, l, mid, ql, qr, vec), getpos(x << 1 | 1, mid + 1, r, ql, qr, vec);
}int query(int l, int r, int64_t c) {std::vector<std::pair<int, int>> vec;getpos(1, 1, n, l, r, vec);int L = -n, R = n;for (; L != R;) {int mid = (L + R) >> 1;int64_t crs = 0;for (auto [x, w] : vec) crs += 1ll * w * t[t[x].rs].cnt;if (c <= crs) {L = mid + 1;for (auto &[x, w] : vec) x = t[x].rs;} else {c -= crs, R = mid;for (auto &[x, w] : vec) x = t[x].ls;}}return L;
}void dickdreamer() {std::cin >> n >> m;for (int i = 1; i <= m; ++i) {int op, l, r; int64_t c;std::cin >> op >> l >> r >> c;if (op == 1) update_arr(1, 1, n, l, r, c);else std::cout << query(l, r, c) << '\n';}
}int32_t main() {
#ifdef ORZXKRfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
#endifstd::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);int T = 1;// std::cin >> T;while (T--) dickdreamer();// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/899397.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【作业3】结对项目:实现一个自动生成小学四则运算题目的命令行程序

⭐成员:3223004473詹艺珏 and 3223004301吴梦琪 📎Github链接:https://github.com/Jue610/Jue610/tree/main/ArithProbelm这个作业属于哪个课程 23软件工程这个作业要求在哪里 【作业3】结对项目这个作业的目标 实现一个自动生成小学四则运算题目的命令行程序,培养团…

用ESP32做一个遥控机械臂

RC汽车机械臂只是一个有轮子的RC汽车。该机械臂是一个四自由度机械臂,这意味着它有四个运动部件。我使用mg90伺服电机,因为它们是金属的,但塑料sg90也应该工作。如下图所示。我使用了两个独立的电源,每个都由2S锂离子(Li-on)电池组成,一个用于MCU,另一个用于电机。这是为…

最小化安装Ubuntu

最小化安装 前言: 有时候需要搭建虚拟机,每一次都需要去找文章,搞小半天才能完成环境搭建 这一次写一篇文章记录一下,目的是以后能比较快速简单的搭建好环境 概要 最小化安装需要手动启用网卡 安装防火墙 ⇒ 打开某些端口确保ssh连接等 安装openssh-server openssh-client ⇒ …

愤怒的小鸟

Day 2025/2/20愤怒的小鸟剪切精灵图-改sprite mode为mutiple在sprite editor中slice设置弹弓与鸟的层级关系layer-player 鸟加springjoint组件-distance-0.3-autodistance关闭弹弓组件的一些基本属性:Distance:两点之间的固定距离(设定完有剩余的距离就是可拉伸的长度)Freq…

通过振动传感器,触发水的运动并将其转换为声音

“微挑战”是在巴塞罗那IAAC的“紧急未来设计硕士”课程中为期一周的工作坊。在这一周,我们有时间、空间和专业人士的支持来创建一个功能原型,它也可以是一个投机性的人工制品,有助于我们的个人研究和实践。这个原型应该基于迭代和使用:数字制造工具、生物制造、人工智能、…

单链表练习与重下AS

1.练习题:我的代码答案: /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* reverseList(struct ListNode* head) {struct ListNode dummpy;struct ListNode* tmp;dummpy.next=NULL;//引入临时…

pycharm连接autodl服务器

昨天听舍友说,他们第一个实验都跑完了,瞬间焦虑起来,原来落后这么多,完事昨天晚上7点开始看教程,配环境,看了好几个教程,每个教程都不一样竟然!然后问舍友,舍友说:你先知道你要跑什么项目,我说:我知道啊,我要做什么项目,想要什么结果,我都知道,项目和代码都有,…

shell脚本报错:test.sh: line 2: $\r: command not found

问题 在win上写好shell脚本,传到linux服务器运行调试的时候报错:test.sh: line 2: $\r: command not found 原因 这个错误是由于脚本文件的换行符问题引起的。Windows和Linux系统的换行符不同:Windows使用\r\n(回车+换行)。 Linux使用\n(换行)。脚本是在Windows上编辑的…

Power Apps 技术分享:制作响应式布局

前言Power Apps的一大优势就是可以不用多长时间,就能够配置出响应式布局。正文1.我们先新建一个屏幕,用来演示,如下图:2.添加一个横向容器,修改一下宽和高,根据屏幕尺寸自适应,如下图:逻辑应该蛮好理解的,就是用app的宽,减去当前控件距离顶部的距离的两倍,也就是上下…

day:22 python函数(5)——常用函数

一.len函数 print(len(列表名)) 定义:返回一个内容长度 案例: list=[1,2,3,4,5,6] print(len(list))二.abs 绝对值 print(abs(数值))输出绝对值 案例: a=-9 print(abs(a))三.id() print(id(表名)) 返回一个对象地址,返回对象唯一地址,标示一个整数 list=[1,2,3…

day:22 python函数(4)——文档

一.打开文档 open函数 open() 函数用于打开一个文件,创建一个 file 对象 语法:open(file, mode),模式有r(只读),w(写入覆盖), a(写入追加) (1)查看open所有功能 按住ctrl键,鼠标点击open关键字,查看用法(2)读取python中复制的路径 a.复制py文件的路径 path1=r"C:\U…

day:22 python函数(3)——内置函数和压缩

一.python的内置函数二.内置函数使用 1.format()函数 定义:是一格式化字符串,可以将变量或值插入到字符串的特点位置,使字符串的建构更加的灵活和易读,增强了字符串格式的功能. 2.基本语法 通过{}来代替以前的% 3.案例 a.不设置指定位置,默认顺序 hz="{}{}".format…