「PKUSC2018 星际穿越」Solution

news2024/11/28 19:00:02

题目传送门

[PKUSC2018] 星际穿越

简述题意

给定一张 n n n 个点的无向图和 q q q 次询问,每一个点 i i i ∀ j ∈ [ l i , i − 1 ] \forall j \in [l_i , i -1] j[li,i1] 都存在一条长度为 1 1 1 的无向边,每次询问给定 l i , r i , x i l_i,r_i,x_i li,ri,xi,求 1 r i − l i + 1 ∑ y = l i r i d i s t ( x i , y ) \frac{1}{r_i-l_i+1}{\sum_{y=l_i}^{r_i}{dist(x_i,y)}} rili+11y=liridist(xi,y) 的最简分数形式。

  • n , q ≤ 3 × 1 0 5 , 1 ≤ l i < r i < x i ≤ n n,q\leq 3\times 10^5,1\le l_i < r_i < x_i \le n n,q3×1051li<ri<xin

思路

Subtask1 & 2

直接把图建出来,对每一个点暴力跑一遍 dijkstra \text{dijkstra} dijkstra,每次询问累和即可。
时间复杂度 O ( n 2 l o g n ) O(n^2logn) O(n2logn),可以得到 45 p t s 45pts 45pts

Subtask3

与正解强相关

先把图降维成序列问题,把 n n n 个点抽象成 n n n 个元素的序列 a a a

考虑贪心,由于 l i < r i < x i l_i < r_i < x_i li<ri<xi,因此一定尽可能往右跳,才能最小化步数。
不妨令 n x t i , j nxt_{i,j} nxti,j 表示从 i i i 开始跳 j j j 步,能到达的最小点。

显然 n x t i , 0 = l i nxt_{i,0} = l_i nxti,0=li,然而 n x t i , 1 nxt_{i,1} nxti,1 一定等于 l l x i l_{l_{x_i}} llxi 嘛?

不是。如果有一个点 j ∈ [ l x i , i − 1 ] j \in [l_{x_i},i-1] j[lxi,i1] 满足 l j ≤ l l x i l_j \le l_{l_{x_i}} ljllxi,那么跳到 j j j 一定比跳到 l x i l_{x_i} lxi 更优,因此有:

n x t i , j = min ⁡ { l n x t i , j − 1 , . . . , l i − 1 , l i , l i + 1 , . . . , l n } nxt_{i,j}=\min\{l_{nxt_{i,j-1}},...,l_{i-1},l_i,l_{i+1},...,l_n\} nxti,j=min{lnxti,j1,...,li1,li,li+1,...,ln}

为什么要考虑 [ i + 1 , n ] [i+1,n] [i+1,n] 这一部分呢?因为有可能往右跳比往左跳更优,举个例子可能更形象:
在这里插入图片描述

假如 5 5 5 是起点, 1 1 1 是终点,那么很显然 5 → 6 5 \rightarrow 6 56 5 → 4 5 \rightarrow 4 54 更优。

因此枚举每个点作为起点,进行一次上述过程即可。
最坏时间复杂度 O ( n 2 ) O(n^2) O(n2),可以得到 75 p t s 75pts 75pts

Subtask4

上述做法中,发现我们的时间复杂度瓶颈在于 j j j 这一维,而且正解时间复杂度应该是 O ( n l o g n ) O(nlogn) O(nlogn),这都启发我们倍增。

不妨令 d p i , j dp_{i,j} dpi,j 表示从 i i i 开始跳 2 j 2^j 2j 步能够到达的最小点。

那么有经典倍增式 d p i , j = d p d p i , j − 1 , j − 1 dp_{i,j} = dp_{dp_{i,j-1},j-1} dpi,j=dpdpi,j1,j1

然后显然有 d p i , 0 = l i dp_{i,0}=l_i dpi,0=li?大多数人的第一想法可能都是这样初始化,然而这显然是错的!
再举个例子。

在这里插入图片描述
如上图,如果这样初始化就有 d p 5 , 1 = d p d p 5 , 0 , 0 = d p 3 , 0 = 2 dp_{5,1}=dp_{dp_{5,0},0}=dp_{3,0}=2 dp5,1=dpdp5,0,0=dp3,0=2,然而显然可以 5 → 4 → 1 5 \rightarrow 4 \rightarrow 1 541,为什么会出错呢?由 subtask3 \text{subtask3} subtask3 的做法可得,我们没有考虑往右跳的情况。

然而每个点都会出现往右跳的情况吗?
显然不是。具体地,有如下引理:

引理:
在任意最优情形下,只有起点可能往右跳,其他点一定只会向左跳。
证明也是显然的,如果当前点往右跳到 x x x 更优,那为何不直接从上一个点(一定会有前驱点)跳到 x x x 呢?

因此,我们只需要考虑起点往右跳的情况,就可以保证递推的重要性,因此 d p i , 0 = min ⁡ { l i , l i + 1 , . . . , l n } dp_{i,0}=\min\{l_i,l_{i+1},...,l_n\} dpi,0=min{li,li+1,...,ln}(至于那些 i i i 往右跳无法到达的点一定有 l j > i l_{j} > i lj>i,所以考虑了也无所谓),发现这样初始化代入上述例子也是对的。

考虑如何回答询问。不妨令 s u m i , j sum_{i,j} sumi,j 表示 i i i [ d p i , j , i − 1 ] [dp_{i,j},i-1] [dpi,j,i1] 的距离和。
那么有 s u m i , 0 = i − d p i , 0 sum_{i,0}=i-dp_{i,0} sumi,0=idpi,0

  • 先考虑 [ d p i , j − 1 , i − 1 ] [dp_{i,j-1},i-1] [dpi,j1,i1] 这一部分的贡献,即 s u m i , j − 1 sum_{i,j-1} sumi,j1
  • 再考虑 [ d p i , j , d p i , j − 1 − 1 ] [dp_{i,j},dp_{i,j-1}-1] [dpi,j,dpi,j11] 这一部分的贡献,我们已知从 d p i , j − 1 dp_{i,j-1} dpi,j1 这个点走到这些点的距离,即为 s u m d p i , j − 1 , j − 1 sum_{dp_{i,j-1},j-1} sumdpi,j1,j1,所以只需要从 i i i 2 j − 1 2^{j-1} 2j1 d p i , j − 1 dp_{i,j-1} dpi,j1,一共要走 d p i , j − 1 − d p i , j dp_{i,j-1}-dp_{i,j} dpi,j1dpi,j 次。

总结一下有:
s u m i , j = s u m i , j − 1 + s u m d p i , j − 1 , j − 1 + 2 j − 1 × ( d p i , j − 1 − d p i , j ) sum_{i,j}=sum_{i,j-1}+sum_{dp_{i,j-1},j-1}+2^{j-1}\times(dp_{i,j-1}-dp_{i,j}) sumi,j=sumi,j1+sumdpi,j1,j1+2j1×(dpi,j1dpi,j)

注意,在上述推导过程中,我们并未考虑从起点往右跳的贡献,这一部分会在后文详细阐述。

求得 d p , s u m dp,sum dp,sum 以后,即可处理询问:

在这里插入图片描述
该函数旨在求出求出 x x x 走到 [ l p o s , x − 1 ] [lpos, x-1] [lpos,x1] 的距离和。

有注释的部分应该很好理解,瓶颈在于框出的两行代码,网上大多数题解这一部分都没有写明白。

为什么要强制走到 l x l_x lx 呢?注意到,我们之前 s u m sum sum 的推导并没有考虑 x x x 最开始往右跳的贡献,所以我们要强制选择一个点,那么为什么选择了 l i l_i li 呢?

  • 如果 x x x 最开始向右跳到 y y y 更优,那么从 l x l_x lx 出发可以且一定会跳到 y y y,就等价于 x x x 跳到 y y y,区别在于 l x l_x lx 出发可以顺便处理这一部分的贡献。
  • 如果 x x x 最开始向左跳到 x x x 更优,同理,从 l x l_x lx 出发也一定会跳到 y y y

通俗的讲,先强制选择 l x l_x lx 其作用就在于等着被替代成其他点。表面上从 x x x 跳到了 l x l_x lx,实际是从 x x x 跳到了 y y y
x → l x → y x \rightarrow l_x \rightarrow y xlxy 等价于 x → y x \rightarrow y xy,但前者可以处理向右跳的贡献。

结合样例可以更好理解。
在这里插入图片描述

如果 6 6 6 为起点,那么我们会强制跳到 4 4 4,表面上错过了可以直达 1 1 1 5 5 5,但是 4 4 4 是可以且一定会向右跳到 5 5 5 的,因为我们的倍增是最优的。

代码

一道非常好的倍增题!!!

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 3e5 + 5;
int n , q , dp[MAXN][20] , sum[MAXN][20] , l[MAXN];
int solve(int x , int lpos) { // 求出 x 走到 [lpos , x-1] 的距离和
	if (l[x] <= lpos) return x - lpos; // 特判一步走到的情况
	int ans = x - l[x] , step = 1;
	x = l[x];
	for (int i = 19 ; i >= 0 ; i --) { 
		if (dp[x][i] >= lpos) {// 只要还未到达终点,就不断往前倍增跳
			ans += (x - dp[x][i]) * step + sum[x][i]; // 和 sum 的推导类似
			x = dp[x][i] , step += (1 << i); // step 表示当前走过的步数
		}
	}
	step ++;
	if (x > lpos) ans += (x - lpos) * step; // 处理不能恰好到达 x 的情况
	return ans;	
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	cin >> n;
	for (int i = 2 ; i <= n ; i ++) cin >> l[i] , dp[i][0] = l[i];
	for (int i = n - 1 ; i >= 2 ; i --) dp[i][0] = min(dp[i + 1][0] , dp[i][0]);
	for (int i = 1 ; i <= n ; i ++) sum[i][0] = i - dp[i][0];
	for (int j = 1 ; j <= 19 ; j ++) {
		for (int i = 2 ; i <= n ; i ++) {
			dp[i][j] = dp[dp[i][j - 1]][j - 1];
			sum[i][j] = sum[i][j - 1] + sum[dp[i][j - 1]][j - 1] + (dp[i][j - 1] - dp[i][j]) * (1 << j - 1);
		}
	}
	cin >> q;
	while(q --) {
		int ql , qr , x;
		cin >> ql >> qr >> x;
		int div = (qr - ql + 1) , w = solve(x , ql) - solve(x , qr + 1);
		int g = __gcd(div , w);
		w /= g , div /= g; // 约分
		cout << w << '/' << div << '\n';
	}
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DRF的三大认证

【 零 】一些注意事项 【1】如何使用视图类 #1 APIView -如果后续&#xff0c;写个接口&#xff0c;不需要用序列化类&#xff0c;不跟数据库打交道-发送短信接口&#xff0c;发送邮件接口#2 GenericAPIView-如果后续&#xff0c;写个接口&#xff0c;要做序列化或跟数据库打交…

数据结构复习指导之线索二叉树

文章目录 二叉树 考纲内容 复习提示 1.线索二叉树 1.1线索二叉树的基本概念 1.2中序线索二叉树的构造 1.3中序线索二叉树的遍历 1.4先序线索二叉树和后序线索二叉树 知识回顾 二叉树 考纲内容 &#xff08;一&#xff09;树的基本概念 &#xff08;二&#xff09;二叉…

酷柚易汛ERP源码部署/售后更新/搭建/上线维护

一款基于FastAdminThinkPHPLayui开发的ERP管理系统&#xff0c;帮助中小企业实现ERP管理规范化&#xff0c;此系统能为你解决五大方面的经营问题&#xff1a;1.采购管理 2.销售管理 3.仓库管理 4.资金管理 5.生产管理&#xff0c;适用于&#xff1a;服装鞋帽、化妆品、机械机电…

代码审计-PHP模型开发篇动态调试反序列化变量覆盖TP框架原生POP链

知识点 1、PHP审计-动态调试-变量覆盖 2、PHP审计-动态调试-原生反序列化 3、PHP审计-动态调试-框架反序列化PHP常见漏洞关键字 SQL注入&#xff1a; select insert update delete mysql_query mysqli等 文件上传&#xff1a; $_FILES&#xff0c;type"file"&…

人工智能驱动的设计工具的兴起:彻底改变创意产业

人工智能驱动的设计工具的兴起&#xff1a;彻底改变创意产业 概述 人工智能 (AI) 正在改变创意产业&#xff0c;设计也不例外。人工智能驱动的设计工具正在彻底改变设计师的工作方式&#xff0c;提供无与伦比的效率、创造力和创新水平。从生成图像和设计到自动化日常任务&…

深度学习基础之《TensorFlow框架(17)—卷积神经网络》

一、卷积神经网络介绍 1、背景 随着人工智能需求的提升&#xff0c;我们想要做复杂的图像识别&#xff0c;做自然语言处理&#xff0c;做语义分析翻译等等&#xff0c;多层神经网络的简单叠加显然力不从心 2、卷积神经网络与传统多层神经网络对比 &#xff08;1&#xff09;传…

Java基础编程(高级部分)

1. 类变量和类方法 1.1 什么是类变量 类变量也叫静态变量/静态属性&#xff0c;是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值同样任何一个该类的对象去修改它时,修改的也是同一个变量。 1.2 定义类变量 1.3 访问类变量 类名.类变量名 或者 对…

【C语言】模拟实现深入了解:字符串函数

&#x1f525;引言 本篇将模拟实现字符串函数&#xff0c;通过底层了解更多相关细节 &#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自…

flowable多对并发网关跳转的分析

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; h…

塑胶ERP系统都有什么用处

在当今竞争激烈的塑胶市场中&#xff0c;企业如何高效地管理从原料采购到产品销售的整个生产链&#xff0c;直接关系到企业的生存与发展。ERP系统作为一种先进的管理信息系统&#xff0c;正逐渐成为塑胶企业不可或缺的工具。那么&#xff0c;一款优秀的ERP系统&#xff0c;究竟…

C语言自定义类型——枚举

枚举 枚举定义枚举 与 #define使用写一个简易计算器的程序。 枚举定义 格式&#xff1a; enum name(枚举什么类型) {//数据 ... };枚举&#xff0c;顾名思义一 一 列举。 在生活当中有很多可以列举的东西。 如&#xff1a; //电脑桌面上的软件 enum App {QQ ,WeChat,CCtalk,…

ESG榜单冲击数据集(2000-2022年)

参照《财经研究》中刘柏&#xff08;2024&#xff09;的做法&#xff0c;以2015年为中点&#xff0c;根据商道荣绿2015年6月公开的ESG榜单数据&#xff0c;构建ESG榜单冲击的DID数据&#xff0c;如果公司属于ESG榜单冲击的公司&#xff0c;且年份≥2015&#xff0c;则为1&#…

OBS插件--视频回放

视频回放 视频回放是一款源插件&#xff0c;它可以将指定源的视频缓存一段时间&#xff08;时间可以设定&#xff09;&#xff0c;将缓存中的视频添加到当前场景中后&#xff0c;可以快速或慢速不限次数的回放。这个功能在类似体育比赛的直播中非常有用&#xff0c;可以捕获指…

Leetcode - 周赛396

目录 一&#xff0c;3136. 有效单词 二&#xff0c;3137. K 周期字符串需要的最少操作次数 三&#xff0c;3138. 同位字符串连接的最小长度 四&#xff0c;3139. 使数组中所有元素相等的最小开销 一&#xff0c;3136. 有效单词 本题就是一道阅读理解题&#xff1a; 字符串长…

Docker Compose常用命令与属性

大家好&#xff0c;今天给大家分享Docker Compose的常用命令&#xff0c;以及docker-compose文件的属性。Docker Compose 是一个用于定义和运行多容器 Docker 应用应用的重要工具。它通过一个配置文件&#xff08;docker-compose.yml&#xff09;来详细定义多个容器之间的关联、…

爬虫-无限debug场景 解决方式

解决无限debug 场景1 1. 鼠标右键 选择 continue to here&#xff08;此处不停留&#xff09;2. 鼠标右键 选择 edite breakpoint 设置 10 保证条件不成立 这行永远不执行3.方法置空 1. 方法调用加断点2. 控制台 setInterval function name() {}4. 替换文件 5. hoo…

如何使用phpMyAdmin删除数据库中的表?

本周有一个客户&#xff0c;购买Hostease的Linux虚拟主机&#xff0c;询问我们的在线客服&#xff0c;如何使用phpMyAdmin删除数据库中的表&#xff1f;我们为用户提供相关教程&#xff0c;用户很快解决了遇到的问题。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可以…

LeetCode63:不同路径Ⅱ

题目描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。那么从左上角…

飞凌嵌入式FET113i-S核心板在国产FTU中的适配性分析

智能电网建设的不断推进&#xff0c;使配电自动化成为了提升电网运行效率、保障供电质量的关键技术。在配电自动化系统中&#xff0c;馈线终端单元&#xff08;FTU&#xff09;作为连接电网与用户的重要节点&#xff0c;承担着实时监控、故障检测与隔离、远程控制等多项关键任务…

SpringMVC传递参数

1.RequestMapping RequestMapping本身可以处理&#xff0c;get或post,指定了get或post之后&#xff0c;就只能处理对应的请求。 RequestMapping(value{"haihiyo","goodMoring"},methodRequestMethod.POST)2.RestFul风格 RestFul是一种风格 比如:网站的访…