题解:[JOISC 2021 Day4] イベント巡り 2 (Event Hopping 2)

news/2024/11/14 22:42:06/文章来源:https://www.cnblogs.com/avalaunch/p/18542504

P7562 [JOISC 2021 Day4] イベント巡り 2 (Event Hopping 2)

lxl 上课讲了这题,我听了选取答案区间的思路,恍然大雾 ,于是就有了这篇题解——

sto lxl orz !!!


本题解主要详解区间选取。

前置知识:倍增


策略

首先,本题的 \(L_i\)\(R_i\) 较大,离散化即可。

另外,我个人觉得把所有的 \(R_i\) 减掉一之后会好写一点,转成了 \([L_i, R_i]\) 区间覆盖。然而我却调了半个多小时

然后问题是:若固定选择一个区间,最大化再向右选择的区间个数。

考虑贪心,每次选择没有交叉、右端点最靠左的。证明显然, 因为如果选择右端点更靠右的区间,那么能选的区间不会变多,答案只可能更劣。

由此一来,从每个区间开始,都有固定的方案来最大化答案,于是就能倍增啦~~

倍增

\(nxt[k][i]\) 表示从 \(i\) 开始选 \(2^k\) 个区间后最靠左的点。

\(nxt\) 数组的初值,可以枚举区间,用右端点更新左端点的 \(nxt\)

\[nxt[0][L_i] = \min\left\{R_i + 1\right\} \]

\(R_i\) 要加一是因为跳完 \([L_i,R_i]\) 这个区间后,下一个要从 \(R_i+1\) 开始)

转移方程也很显然:

\[nxt[k][i] = nxt[k-1][nxt[k-1][i]] \]

另外,由于区间之间可以有空隙,所以还要用 \(nxt[k][i + 1]\) 更新 \(nxt[k][i]\)

怎么样,简单吧?

然后查询 \([L_i, R_i]\) 最多能放几个区间(以下写为 \(\operatorname{query}(L_i,R_i)\))时,只要把 \(k\) 从大往小枚举,能跳尽量跳就行了,可以做到 \(O(log n)\)

如何保证字典序最小?

首先,若 \(\operatorname{query}(1,m)<k\)\(m\) 为值域),肯定无解。

否则,维护一些“块”。初始时块为 \([1,m]\)

然后考虑这样做:从编号 \(1\)\(n\) 枚举区间,若该区间被某一个块包含,并且选择该区间后仍有选择 \(k\) 个区间的方案(可以用 \(\operatorname{query}\) 算出,选它之后,块内最多可选区间个数的变化量来判断),那么直接选择该区间,并回收没有被区间覆盖的块。

如下图。

不难看出,这样做保证了有解的前提下,字典序最小。是不是很妙?

问题来了,要怎么维护“块”呢?方法有很多,这里介绍一种用 set 维护的方法。

写一个结构体,里面存 \(l\)\(r\) ,重载运算符 <r < t.l 。然后可以用 find() 函数找到与区间有交的块,再判断是否包含区间就好了。

注:find(k) 找到的是 x < kk < x 都不满足的元素,所以相当于找与区间有交的块。

然后就做完了。时间复杂度 \(O(nlogn)\)

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, M = 2e5 + 5, LOGM = 19; // N是区间个数,M是值域
int n, K, li[N], ri[N];
int a[M], m; // 离散化数组
int nxt[LOGM][M];
struct range
{int l, r;bool operator<(const range t) const{return r < t.l;}
};
set<range> res; // 维护“块”
vector<int> ans; // 选择的区间int lsh(int x) // 离散化
{return lower_bound(a + 1, a + m + 1, x) - a;
}int query(int l, int r) // 查询[l,r]最多能放几个区间
{if (l > r) return 0;int res = 0;for (int k = LOGM - 1; k >= 0; k--)if (nxt[k][l] <= r + 1){l = nxt[k][l];res += 1 << k;}return res;
}int main()
{cin >> n >> K;for (int i = 1; i <= n; i++){scanf("%d%d", li + i, ri + i);ri[i]--; // 转为[l,r]a[++m] = li[i]; a[++m] = ri[i];}sort(a + 1, a + m + 1);m = unique(a + 1, a + m + 1) - a - 1;for (int k = 0; k < LOGM; k++)for (int i = 1; i <= m + 4; i++)nxt[k][i] = m + 3; // 设为极大值for (int i = 1; i <= n; i++){li[i] = lsh(li[i]), ri[i] = lsh(ri[i]);nxt[0][li[i]] = min(nxt[0][li[i]], ri[i] + 1); // 赋nxt初值,注意要+1!}for (int i = m; i >= 1; i--){nxt[0][i] = min(nxt[0][i + 1], nxt[0][i]); // 用后一个转移for (int k = 1; k < LOGM; k++)nxt[k][i] = min(nxt[k - 1][nxt[k - 1][i]], nxt[k][i + 1]); // 用小的合并}int sum = query(1, m);if (sum < K) // 无解就输出-1{puts("-1");return 0;}res.insert({1, m}); // 初始块为[1,m]for (int i = 1; i <= n; i++){if (res.find({li[i], ri[i]}) == res.end()) continue; // 若没有相交,就肯定没有覆盖auto it = res.find({li[i], ri[i]});range tmp = *it;if (li[i] < tmp.l || tmp.r < ri[i]) continue; // 没有完全覆盖也不能选int delta = query(tmp.l, li[i] - 1) + 1 + query(ri[i] + 1, tmp.r) - query(tmp.l, tmp.r);if (sum + delta >= K) // 若选了该区间之后仍有合法方案{sum += delta;ans.push_back(i);res.erase(it);if (tmp.l <= li[i] - 1) res.insert({tmp.l, li[i] - 1}); // 回收左边剩下的块if (ri[i] + 1 <= tmp.r) res.insert({ri[i] + 1, tmp.r}); // 回收右边剩下的块}if (ans.size() >= K) break; // 选完了}for (auto &&i : ans)printf("%d\n", i);return O; // awa
}

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

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

相关文章

团队作业4——项目冲刺-2

团队作业4——项目冲刺-2信息项 内容课程名称 广工计院计科34班软工作业要求位置 作业要求作业目标 小飞棍团队对需求改进和系统设计进行讨论GitHub链接 GitHub一、团队简介队名:小飞棍队团队成员:姓名 学号罗振烘(组长) 3122004748庄崇立 3122004633李响 3121002802何昌洲…

实验14:代理模式

本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解代理模式的动机,掌握该模式的结构; 2、能够利用代理模式解决实际问题。[实验任务一]:婚介所 婚介所其实就是找对象的一个代理,请仿照我们的课堂例子“论坛权限控制代理”完成这个实际问题,其中如果年纪…

Bulk-Crap-Uninstaller:一个高效卸载,轻松管理你的应用程序的.Net开源工具

我们在工作中,经常需要安装大量的软件,随着应用程序的不断增多,管理这些软件变得非常困难。 下面介绍一款具备高效、简洁的特点,可以帮助我们快速卸载大量不需要的应用程序,让电脑管理变得更加轻松。01 项目简介 Bulk-Crap-Uninstaller是一款开源的软件卸载工具,基于.Net…

绘制3D架构图,原来这么简单

在软件开发的世界里,架构图是系统设计的蓝图,它们不仅帮助团队理解系统的整体结构,还能提升沟通效率,确保项目的顺利推进。然而,绘制一张清晰、直观的架构图,往往需要大量时间和专业工具。面对繁琐的操作和复杂的学习曲线,不少程序员感到力不从心。 之前DD有给大家推荐过…

AI千恋万花(java调用api实现)附完整项目及注释)重置版)

感觉博客的第一版质量有点低下了,删了重置一下,希望能给其他人的代码带来一些灵感前情提要:https://www.cnblogs.com/h4o3/p/18523151 由于是匆忙制作的老婆系统,主界面已经菠萝菠萝哒。(有点廉价) 注册和登录功能用了MySQL实现(其实没什么卵用,为了顺手交个作业临时加…

鲲鹏V10安装人大金仓

1.下载人大金仓数据库 https://www.kingbase.com.cn/xzzx/index.htm 2.创建安装用户 useradd kingbase#将安装包权限赋予kingbase用户chown -R kingbase:kingbase /home/kingbase#创建安装目录并赋权mkdir -p /usr/local/apps/KingbaseESmkdir -p /usr/local/apps/Kingbasechow…

centos7安装elasticsearch:7.9.3

服务器安装elasticsearch:7.9.3 一、安装前准备检查系统环境:确保CentOS 7系统已经更新到最新版本。 检查系统的硬件资源,确保满足Elasticsearch的安装和运行要求。安装OpenJDK:Elasticsearch需要Java环境,这里选择安装OpenJDK 11。 使用命令sudo yum install java-11-open…

Golang 编译windows应用程序

因为我们更喜欢在Linux上开发程序, 所以生成交叉编译器,以便在Linux上交叉编译出windows程序。 安装minGW:在Linux上运行gcc交叉编译生成windows程序 我们用到Cgo,因此需要安装 C 语言交叉编译器 sudo apt-get install gcc-mingw-w64 下载Go语言的源代码 git clone https:/…

The platform metadata area could not be written: /Volumes/MemoryAnalyzer1/MemoryAnalyzer.app/Content

mac安装MAT报错:The platform metadata area could not be written: /Volumes/MemoryAnalyzer1/MemoryAnalyzer.app/Content 。。。。。解决:创建文件夹 /Users/mzj/storage/data/mat/data

Centos7安装部署Nagios

简介 Nagios 是一款自动化运维工具,可以协助运维人员监控服务器的运行状况,并且拥有报警功能。 1、Nagios 核心及插件将安装在/usr/local/nagios 2、Nagios 核心会配置好监控当前服务器的一些基本信息 仅供参考,记录一下centOS7下nagios配置步骤,完整的步骤以及原理请参照原…

全媒体数字化转型,业务和技术双管齐下

不少传媒企业已经开始积极探索转型之路。通过打造个性IP工作室、重视C端用户服务、深化G端合作等方式,传媒行业正在逐步构建起一个以用户为中心、以数据为驱动、以创新为核心的新型媒体生态。2024年,是我国全功能接入国际互联网30周年。 在这个特殊的年份,中国的传媒行业也同…

南谷的往事与未来

纯属娱乐 本人南海实验中学 制作人员信息队自娱自乐在Tail Nightly建了个南谷一位作文大蛇就写下了一篇小说(在更新) 喜剧小说,神话小说 对事不对人,内容纯属虚构,切勿对号入座 南谷的往事与未来 洛谷网址 喜剧小说,神话小说 对事不对人,内容纯属虚构,切勿对号入座 作者…