CF671E Organizing a Race 题解

news/2025/2/24 19:41:00/文章来源:https://www.cnblogs.com/Scarab/p/18734713

Description

\(n\) 个点排成一行,第 \(i\) 个点与第 \(i+1\) 个点之间的距离为 \(w_i\) ​个单位。

每个点都有一个加油站,第 \(i\) 个点的加油站可以给你的车加能跑 \(g_i\) ​个单位的油。

若一辆初始没有油的车能从 \(l\) 一路向右开到 \(r\),也能从 \(r\) 一路向左开到 \(l\),则称 \(l,r\) 之间可以往返。

另外,你有 \(k\) 次将某个 \(g_i\) ​加 \(1\) 的机会。请你求出在 \(l,r\) 之间可以往返的情况下,\(r−l+1\) 的最大值。

\(n\leq 10^5\)\(k,w_i,g_i\leq 10^9\)

Solution

首先考虑对于 \([l,r]\),什么样的 \(g\)\(w\) 能满足条件。容易发现需要满足:

\[\begin{cases} w_l&\leq g_l\\ w_l+w_{l+1}&\leq g_l+g_{l+1}\\ &\vdots\\ \sum_{i=l}^{r-1}{w_i}&\leq \sum_{i=l}^{r-1}{g_i} \end{cases} \]

\[\begin{cases} w_{r-1}&\leq g_r\\ w_{r-1}+w_{r-2}&\leq g_r+g_{r-1}\\ &\vdots\\ \sum_{i=l}^{r-1}{w_i}&\leq \sum_{i=l+1}^{r}{g_i} \end{cases} \]

\(a_k=\sum_{i=1}^{k}{(w_{i-1}-g_{i-1})}\)\(b_k=\sum_{i=1}^{k}{(g_i-w_{i-1})}\),则需要满足 \(a_l=\max_{i=l}^{r}{a_i}\)\(b_r=\max_{i=l}^{r}{b_i}\)

那么让 \(g_i\) 加一,会让 \(a_{i+1},a_{i+2},\ldots,a_{n}\) 减一和 \(b_{i},b_{i+1},\ldots,b_{n}\) 加一。

如果只有 \(a\) 的限制,对于固定的 \(l\) 右边的第一个 \(a_x>a_l\) 的位置 \(x\),需要满足 \([l,x-1]\) 这个区间至少需要操作 \(a_x-a_l\) 次,操作过后对于 \(x\) 右边的第一个位置 \(y\),同样需要满足 \([x,y-1]\) 要操作 \(a_y-a_x\) 次。

这启发我们维护一个单调栈,然后从后往前扫 \(l\),对于栈中的元素 \(c_i\),贪心地选择在 \(g_{c_i-1}\) 操作 \(a_{c_{i-1}}-a_{c_i}\) 次。

同时通过线段树维护出操作后的 \(b\) 数组,题目转化为:区间加,查询最大的 \(r\) 满足 \(\max_{i=l}^{r}{b'_i}-b'_r\leq k'\)

注意到 \(b'_r=b_r+cnt_{<r}\)\(k'=k-cnt_{<r}\),所以转化为查询最大的 \(r\) 满足 \(\max_{i=l}^{r}{b'_i}-b_r\leq k\)

由于这里 \(\max_{i=l}^{r}b'_i\) 包含 \(b'_r\),不利于二分,所以可以先二分出 \(b'_r-b_r\leq k\) 的一个边界 \(r_{max}\),然后变为查询 \([l,r_{max}]\)\(\max_{i=l}^{\color{red}{r-1}}{b'_i}-b_r\leq k\) 的最大 \(r\)

先把区间外的位置加上一个极大值,变成全局查询 \(\max_{i=1}^{r-1}b'_i-b_r\leq k\) 的最大 \(r\)

在线段树上维护区间 \(b_i\) 最大值和 \(b'_i\) 的最大值,以及 \(mxd\) 表示只考虑当前的节点区间 \([l,r]\),右子树里 \(b_i-\max_{j=l}^{i-1}{b'_j}\) 的最大值。\(mxd\) 可以在 pushup 的时候维护。

设当前查询区间为 \([L,R]\),区间前面 \(b'_i\) 的最大值是 \(mx\)。如果 \(mxb_{ls}\leq mx\),说明左子树被 \(mx\) 完全覆盖,所以只需要二分找到左子树里 \(b_i\geq mx-k\) 的最大 \(i\),同时递归右子树。

如果 \(mxb_{ls}<mx\),说明 \(mx\) 不会影响当前区间的右子树,通过 \(mxd\) 的值判断是递归左子树还是右子树即可。

pushup 的过程同理。

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

Code

#include <bits/stdc++.h>#define int int64_tconst int kMaxN = 1e5 + 5;int n, k;
int w[kMaxN], g[kMaxN], a[kMaxN], b[kMaxN];struct BIT {int c[kMaxN];void upd(int x, int v) {for (; x <= n; x += x & -x) c[x] += v;}int qry(int x) {int ret = 0;for (; x; x -= x & -x) ret += c[x];return ret;}
} bit;struct SGT {// int _b[kMaxN];// void build() {//   for (int i = 1; i <= n; ++i) _b[i] = b[i];// }// void update(int x, int l, int r, int ql, int qr, int v) {//   for (int i = ql; i <= qr; ++i) _b[i] += v;// }// int query(int mxr = n) {//   // for (int i = 1; i <= n; ++i) std::cerr << _b[i] << ' ';//   // std::cerr << '\n';//   int ret = 0, mx = -1e18;//   for (int i = 1; i <= mxr; ++i) {//     if (mx - b[i] <= k) ret = i;//     mx = std::max(mx, _b[i]);//   }//   return ret;// }int mxb[kMaxN * 4], mx_b[kMaxN * 4], tag[kMaxN * 4], mxd[kMaxN * 4];void addtag(int x, int l, int r, int v) {mx_b[x] += v, tag[x] += v, mxd[x] -= v;}void pushdown(int x, int l, int r) {if (tag[x]) {int mid = (l + r) >> 1;addtag(x << 1, l, mid, tag[x]), addtag(x << 1 | 1, mid + 1, r, tag[x]);tag[x] = 0;}}int getpos(int x, int l, int r, int v) {if (mxb[x] < v) return 0;if (l == r) return l;int mid = (l + r) >> 1;if (mxb[x << 1 | 1] >= v) return getpos(x << 1 | 1, mid + 1, r, v);else return getpos(x << 1, l, mid, v);}int getmxd(int x, int l, int r, int mx = -1e18) {if (l == r) return b[l] - mx;pushdown(x, l, r);int mid = (l + r) >> 1;// return std::max(query(x << 1, l, mid, mx), query(x << 1 | 1, mid + 1, r, std::max(mx, mx_b[x << 1])));if (mx >= mx_b[x << 1]) {return std::max(mxb[x << 1] - mx, getmxd(x << 1 | 1, mid + 1, r, mx));} else {return std::max(mxd[x], getmxd(x << 1, l, mid, mx));}}void pushup(int x, int l, int r) {mxb[x] = std::max(mxb[x << 1], mxb[x << 1 | 1]);mx_b[x] = std::max(mx_b[x << 1], mx_b[x << 1 | 1]);if (l != r) {int mid = (l + r) >> 1;mxd[x] = getmxd(x << 1 | 1, mid + 1, r, mx_b[x << 1]);}}void build(int x, int l, int r) {if (l == r) return void(mxb[x] = mx_b[x] = b[l]);int mid = (l + r) >> 1;build(x << 1, l, mid), build(x << 1 | 1, mid + 1, r);pushup(x, l, r);}void update(int x, int l, int r, int ql, int qr, int v) {if (l > qr || r < ql) return;else if (l >= ql && r <= qr) return addtag(x, l, r, v);pushdown(x, l, r);int mid = (l + r) >> 1;update(x << 1, l, mid, ql, qr, v), update(x << 1 | 1, mid + 1, r, ql, qr, v);pushup(x, l, r);}int query(int x, int l, int r, int mx) {if (l == r) return mx - b[l] <= k ? l : 0;pushdown(x, l, r);int mid = (l + r) >> 1;if (mx >= mx_b[x << 1]) {return std::max(getpos(x << 1, l, mid, mx - k), query(x << 1 | 1, mid + 1, r, mx));} else {if (mxd[x] >= -k) return query(x << 1 | 1, mid + 1, r, mx_b[x << 1]);else return query(x << 1, l, mid, mx);}}
} sgt;void upd(int x, int v) {sgt.update(1, 1, n, x, n, v);bit.upd(x, v);
}void solve() {static int stk[kMaxN];int top = 0;sgt.build(1, 1, n);sgt.update(1, 1, n, 1, n, -1e18);b[0] = -1e18;int ans = 0;for (int i = n; i; --i) {for (; top && a[stk[top]] <= a[i]; --top) {if (top > 1) upd(stk[top - 1] - 1, -(a[stk[top - 1]] - a[stk[top]]));}stk[++top] = i;if (top > 1) upd(stk[top - 1] - 1, a[stk[top - 1]] - a[stk[top]]);sgt.update(1, 1, n, i, i, 1e18);int L = i - 1, R = n + 1, mxr = i - 1;while (L + 1 < R) {int mid = (L + R) >> 1;if (bit.qry(mid - 1) <= k) L = mxr = mid;else R = mid;}sgt.update(1, 1, n, mxr, n, 1e18);ans = std::max(ans, sgt.query(1, 1, n, -1e18) - i + 1);sgt.update(1, 1, n, mxr, n, -1e18);}std::cout << ans << '\n';
}void dickdreamer() {std::cin >> n >> k;for (int i = 1; i < n; ++i) std::cin >> w[i];for (int i = 1; i <= n; ++i) std::cin >> g[i];for (int i = 1; i <= n; ++i) {a[i] = a[i - 1] + w[i - 1] - g[i - 1];b[i] = b[i - 1] + g[i] - w[i - 1];}solve();
}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/889145.html

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

相关文章

AutoEval

目前文章的共性通过探究 其他方法(多任务学习器)得到的分类器与带原始标签的合成数据集分类器 的相关关系。得出一个可以应用在无标签且含有分布偏移的真实世界数据上,分类效果较好的分类器。【Frechet distance(Auto-eval),Rotation Prediction(Weijian Deng, Stephen …

开学测验——仓库管理系统

以下是项目结构:登录界面:输入不同用户名进入不同角色的主页面管理员:仓库工作人员:

【窃贼】- 2025.2.24

下图为《Balatro》中的一张小丑牌:【窃贼】窃贼是小丑牌中一张独一无二的小丑,其效果为 \(+3\) 出牌次数并失去所有弃牌次数。其能力相当强大,因为 \(+3\) 出牌次数涵盖了非常多的方面。首先 \(+3\) 出牌次数显然可以拉高分数,提升幅度在绝大多数情况下至少带来 \(\times 1…

2025-2 好题

2025-2 好题 目录2025-2 好题UOJ Round 29 B - 数字生命P10063 [SNOI2024] 平方数AGC070C - No StreakAGC070B - Odd Namoriリテラチュアブルーアーカイブ UOJ Round 29 B - 数字生命 首先想到差分,差分后是正的就看成一些起点,负的就看成是一些终点 然后题目就相当于要对每一…

智算超凡| 触想携手DeepSeek,探索工业+AI应用新模式!

近年来,AI赋能工业场景的应用趋势越发明显,尤其DeepSeek大模型凭借强大的多场景理解与生成能力横空出世,瞬间点燃了“工业+AI”应用的无限遐想。一、DeepSeek火出圈,工业AI加速部署以此为契机,触想于日前启动了DeepSeek大模型在其工业一体机、工控机等产品上的多轮对接与本…

【攻防世界】hit_the_core

core文件如果bin文件内容过多,可以用linux的strings命令辅助分析

【攻防世界】神奇的Modbus

ModBus是工业领域常用的设备之间通信的协议在modbus数据包中追踪字节流即可得到flag

kettle调度管理系统XXK-PDI,kettle调度好帮手

最近两天感冒了,而且莫名其妙的嗓子哑了好几天,心情很是不爽。周末两天啥也不想干,坐在电脑旁边继续手撕kettle调度系统。 1、其实之前有整理过kettle的调度方法,有很多种,根据自己的需求合理选择其中的一种,如下图所示:2、kettlePack 应该是深度集成kettle,将kettle的…

记录---Vue的scoped原理是什么?

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣前言还记得几年前我去找前端工作的时候,那时候才初入职场,有一次去面试,然后被面试官问过一个面试题,Vue中Scoped的原理是什么?幸好当时八股文面试题背的很多,我当时就说是在选择器加了一个唯一的属性实现的,那时候…

用链表实现队列

问题:链表和数组,哪个队列更快? 分析:队列是先进后出 数组是连续存储的,push很快,shift 很慢   链表是非连续存储,add 和 delete 都很快 结论:链表实现队列更快链表实现队列单向链表,要同时记录 head 和 tail 要从tail 入队,从head 出队 length要实时记录,不可遍历…