当前位置: 首页 > news >正文

CF 2156E Best Time to Buy and Sell Stock

直接求解答案似乎并不容易,因为需要考虑的大小关系太多了,于是可以尝试二分转为 01 问题

于是尝试思考,如何判断答案是否 \(\ge w\)

这个问题并不具有一些特殊的结构,所以可以先考虑一点暴力的解法。

因为答案只与二元组 \((i, j)\) 有关,可以转为图论问题,即对 \(a_j - a_i\ge w(i < j)\)\((i, j)\) 连边,先手赢需要满足最后每一条边都有至少一个点被删除,后手赢需要满足最后存在一条边的两个端点都没被删除,若后手赢则说明答案 \(\ge w\)

此时可以考虑一些特例。
比如说如果整个图只有一条边 \((1, 2)\),那么先手是必赢的,因为一个点只会有唯一的配对,后手选取了其中一个,先手就可以删掉另一个。

于是可以知道,若所有点的度数都 \(\le 1\),先手是必赢的。
那如果存在点的度数 \(\ge 1\),会发现一旦来到了后手操作,此时后手必赢,因为后手可以先固定下这个点,先手不管删掉哪个点,该点都至少有 \(1\) 个邻点可以固定。

不过上面的分析都是基于让后手先操作的,实际上先手可以先操作一步,于是直接枚举先手第一步删掉哪个点,再进行上面的判定,就可以做到 \(\mathcal{O}(n^2)\) 的复杂度。

考虑继续挖掘性质。

发现如果删掉一个点,对于其他点的度数影响至多 \(-1\)
那么如果其他点中有度数 \(\ge 3\) 的点,删掉后度数也至少 \(\ge 2\),一定后手赢。

于是可以根据图中度数 \(\ge 3\) 的点数进行分讨:

  • \(\ge 2\),那么一定有一个点不会被删去,后手必赢。
  • \(= 1\),那么第一步一定删掉这个点。
  • \(= 0\),那么剩余点的度数一定 \(\le 2\),此时枚举删掉每个点时只遍历这个点的邻点判断即可。

于是 check 就做到了 \(\mathcal{O}(n)\) 的复杂度。

不过刚刚忽略了处理连边的部分,如果边数到了 \(\mathcal{O}(n^2)\) 级别依然不能接受。

分析上面的过程,发现过程中我们只关心一个点的度数是否 \(\ge 3\)
这说明我们只需要对每个点保留权值最大的 \(3\) 条边,那么就可以维护这个点前面的点权前 \(3\) 小和后面的点权前 \(3\) 大。

时间复杂度 \(\mathcal{O}(n\log V)\)

#include <bits/stdc++.h>using ll = long long;constexpr ll inf = 1e10;
constexpr int N = 1e5 + 10;int n, a[N];
std::pair<ll, int> now[4], pi[N][6];
int c[N];inline bool check(ll bound) {int cnt = 0, lst = 0;for (int i = 1; i <= n; i++) {c[i] = 0;while (c[i] < 3 && pi[i][c[i]].first >= bound) {c[i]++;}if (c[i] >= 3) {if (lst) {return true;} else {lst = i;}}cnt += c[i] >= 2;}if (cnt == 0) {return false;}if (lst) {for (int i = 1; i <= n; i++) {if (i == lst) {continue;}if (i < lst) {c[i] -= a[lst] - a[i] >= bound;} else {c[i] -= a[i] - a[lst] >= bound;}if (c[i] >= 2) {return true;}}return false;} else {for (int i = 1; i <= n; i++) {if (c[i] == 2) {int _cnt = 1;for (int j = 0; j < 2; j++) {_cnt += c[pi[i][j].second] == 2;}if (cnt == _cnt) {return false;}}}return true;}
}inline void solve() {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);}now[0] = now[1] = now[2] = {inf, 0};for (int i = 1; i <= n; i++) {for (int j = 0; j < 3; j++) {pi[i][j] = {a[i] - now[j].first, now[j].second};}for (int j = 0; j < 3; j++) {if (a[i] < now[j].first) {for (int k = 2; k > j; k--) {now[k] = now[k - 1];}now[j] = {a[i], i};break;}}}now[0] = now[1] = now[2] = {-inf, 0};for (int i = n; i >= 1; i--) {for (int j = 0; j < 3; j++) {pi[i][3 + j] = {now[j].first - a[i], now[j].second};}for (int j = 0; j < 3; j++) {if (a[i] > now[j].first) {for (int k = 2; k > j; k--) {now[k] = now[k - 1];}now[j] = {a[i], i};break;}}}for (int i = 1; i <= n; i++) {std::sort(pi[i], pi[i] + 6, std::greater<>());}ll l = -1e9, r = 1e9, ans = -1e9;while (l <= r) {ll mid = (l + r) / 2;if (check(mid)) {ans = mid, l = mid + 1;} else {r = mid - 1;}}printf("%lld\n", ans);
}int main() {int t;scanf("%d", &t);while (t--) {solve();}return 0;
}
http://www.zskr.cn/news/51419.html

相关文章:

  • 《重生之我成为世界顶级黑客》第七章:成功了,但没完全成功
  • 实用指南:Open Inventor 2025.2 FOR JAVA
  • 2025年中小学生 AI 学习机选购指南:松鼠 AI 双线模式成优选
  • 20232305 2025-2026-1 《网络与系统攻防技术》实验五实验报告
  • 网络分析模型六
  • Docker - 配置镜像站解决下载镜像的网络问题
  • Linux问题
  • 20232424 2025-2026-1 《网络与系统攻防技术》实验五实验报告
  • 【C++STL :stack queue (二) 】stack 与 queue 的模拟实现与双端队列探秘 - 指南
  • 《重生之我成为世界顶级黑客》第五章:失败,失败,还是失败
  • 利用单片机的TIM模块播放春日影
  • warp-cli代理
  • 20231427田泽航tlcp协议验证
  • 20232412 2024-2025-1 《网络与系统攻防技术》实验五实验报告
  • 本地缓存Caffeien
  • 实用指南:C++---嵌套类型(Nested Types)封装与泛型的基石
  • python: 用pyppeteer以无头方式抓取页面
  • python共享内存的读写同步与加锁 —— multiprocessing.Value和multiprocessing.Array、加锁
  • 2025年11月温州律师事务所最新推荐,聚焦资质、案例、服务的五家机构深度解读!
  • UI设计公司审美积累|办公类软件界面设计巧思,效率与视觉的双重升级
  • 详细介绍:AVL树手撕,超详细图文详解
  • 网络安全
  • Zhengrui 11.16 总结
  • C# 高级类型 dynamic,list,泛型(学习笔记5)
  • 构建AI智能体:六十九、Bootstrap采样在大模型评估中的应用:从置信区间到模型稳定性 - 指南
  • pip安装或查看工具包时显示WARNING: Ignoring invalid distribution -XX的解决办法
  • 11 月 12 日
  • 详细介绍:LeetCode //C - 893. Groups of Special-Equivalent Strings
  • 2025年国内烘干技术厂家排行榜:十大优质供应商深度评测
  • 2025年烘干技术源头厂家推荐排行榜前十名