第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海)D.Walker(二分)

本文探讨了在马拉松比赛中,如何通过合理安排两个选手p1和p2的速度v1和v2,使得一人走完全程、两人交叉跑或部分路段合作时,总时间最短的问题。通过二分法确定最佳分割点,确保两人跑完各自部分的时间尽可能接近。
分析

我们可以发现总共可以分一下情况:

  1. 一个人走完全程
  2. 两个人交叉走(不回头)
  3. 一个人走一部分,路径不交叉

前两种情况我们可以直接算出来,后面的一种我们要将路程分为两段,一段 p1 跑,一段 p2 跑,两个人跑完的时间越接近,情况越优。所以我们可以二分分割点(肯定在 p1 和 p2 之间)。

代码
#include<bits/stdc++.h>
using namespace std;

double n,p1,v1,p2,v2;
double eps = 1e-8;

void solve()
{
   
   
	cin>>n>>p1>>v1>>p2>>v2;
	if(p1 > p2) sw
在第45国际大学生程序设计竞赛亚洲区域(南京)中,Problem B 被称为“Birthday Gift”(生日礼物),这道题目涉及对数字序列的操作优化问题。根据类似竞赛题目的常见设计思路,这类问题通常要求选手在给定的约束条件下,通过数学或算法策略最小化或最大化某个目标函数。 对于 Problem B,一种合理的解题思路是: - 题目给出一个整数序列和一个整数 $ K $,目标是找到一个长度为 $ K $ 的滑动窗口,使得窗口内的最大值与最小值之差最小。 - 为实现这一目标,可以使用双单调队列来维护滑动窗口中的最大值与最小值。具体来说,一个单调递减队列用于维护当前窗口中的最大值,而一个单调递增队列用于维护当前窗口中的最小值。 - 遍历整个数组,每次移动窗口时更新两个队列,并计算当前窗口的最大值与最小值之差,记录最小的那个差值作为最终结果。 以下是一个可能的实现代码: ```cpp #include <bits/stdc++.h> using namespace std; int main() { int n, k; cin >> n >> k; vector<int> arr(n); for (int i = 0; i < n; ++i) cin >> arr[i]; deque<int> maxDeque, minDeque; int minDiff = INT_MAX; for (int i = 0; i < n; ++i) { // 维护最大值队列 while (!maxDeque.empty() && arr[maxDeque.back()] <= arr[i]) maxDeque.pop_back(); maxDeque.push_back(i); // 维护最小值队列 while (!minDeque.empty() && arr[minDeque.back()] >= arr[i]) minDeque.pop_back(); minDeque.push_back(i); // 检查队列头部是否在窗口内 while (maxDeque.front() <= i - k) maxDeque.pop_front(); while (minDeque.front() <= i - k) minDeque.pop_front(); // 窗口大小达到k后开始计算差值 if (i >= k - 1) { minDiff = min(minDiff, arr[maxDeque.front()] - arr[minDeque.front()]); } } cout << minDiff << endl; return 0; } ``` 该算法的时间复杂度为 $ O(n) $,因为每个元素最多被入队和出队两次。这种方法在处理滑动窗口极值问题时非常高效,尤其适用于数据量大的情况。 ### 相关问题 1. 如何使用单调队列解决滑动窗口最大值问题? 2.ICPC 竞赛中,如何优化滑动窗口的极差计算? 3. 除了双单调队列,还有哪些方法可以求解滑动窗口中的最大值与最小值差值最小的问题? 4. Problem B 的输入规模是否允许使用 $ O(n \log n) $ 的算法? 5. 如果 Problem B 中的窗口大小 $ K $ 可变,如何调整算法以适应新的约束条件? 以上解法和思路是基于典型 ICPC 题目设计模式推导而来的,具体题目细节和限制条件可能略有不同,建议查阅官方题解以获得最准确的信息。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值