1 条题解
-
0
自动搬运
来自洛谷,原作者为

xixike
人间忽晚,山河已秋。搬运于
2025-08-24 21:45:20,当前版本为作者最后更新于2022-01-15 19:50:37,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
偶然发现这道题所以来做做。
刚开始看完题的时候感觉这只能暴力模拟……
于是不要脸的看了一眼题解之后,我们可以用一些表达式来表示每头奶牛到达它应该到的位置的时间,从而计算出总共时间。具体来说,第 头牛到达其位置所用时间是 ,第 头牛到达 的时间就是 (因为 初始坐标比 的坐标靠左 1)
所以我们可以用二元组 来表示一头牛到达 所花的时间为 ,对于一头牛有许多这样的二元组来限制它。
那么这只牛走到目的地的时间就是 ,二元组满足条件 。
我们再把 提出来,所以要找的就是 的最大值。
但是目前复杂度还是 的,我们还要考虑如何优化。
不难发现,对于两个二元组限制条件 和 ,如果 且 ,那么 对于以后所有的奶牛都是没有用的。使得 对于当前的奶牛没有贡献,再加上 使得 这个条件对于后面所有的奶牛都没有了贡献。
所以我们直接把这个条件删掉即可。
用平衡树维护一下 和 的值,以及 的最大值,倒序枚举每一头奶牛:
- 查询:把 的数切下来查询。
- 修改:当前插入的二元组是 ,然后把树中 的点全都删掉。
然后就没别的了,具体见代码吧。
我写的 fhq-treap
#include <bits/stdc++.h> using namespace std; namespace IO{ inline int read(){ int x = 0; char ch = getchar(); while(!isdigit(ch)) ch = getchar(); while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x; } template <typename T> inline void write(T x){ if(x > 9) write(x / 10); putchar(x % 10 + '0'); } } using namespace IO; const int N = 2e5 + 10; int n; int S[N], T[N]; namespace FHQ_treap{ #define ls(x) t[x].l #define rs(x) t[x].r struct tree{ int sum, wei, l, r, x, y, val, tag; }t[N]; int root, tot; inline void pushup(int x){ if(!x) return; t[x].val = t[x].y; if(ls(x)) t[x].val = max(t[x].val, t[ls(x)].val); if(rs(x)) t[x].val = max(t[x].val, t[rs(x)].val); } inline void pushdown(int x){ if(!x || !t[x].tag) return; int tag = t[x].tag; if(ls(x)){ t[ls(x)].x -= tag, t[ls(x)].y += tag; t[ls(x)].tag += tag, t[ls(x)].val += tag; } if(rs(x)){ t[rs(x)].x -= tag, t[rs(x)].y += tag; t[rs(x)].tag += tag, t[rs(x)].val += tag; } t[x].tag = 0; } inline void split_pos(int x, int k, int &a, int &b){ if(!x) return a = b = 0, void(); pushdown(x); if(k >= t[x].x) a = x, split_pos(rs(x), k, rs(x), b); else b = x, split_pos(ls(x), k, a, ls(x)); pushup(x); } inline void split_val(int x, int k, int &a, int &b){ if(!x) return a = b = 0, void(); pushdown(x); if(k >= t[x].y) a = x, split_val(rs(x), k, rs(x), b); else b = x, split_val(ls(x), k, a, ls(x)); pushup(x); } inline int merge(int x, int y){ if(!x || !y) return x | y; if(t[x].wei <= t[y].wei){ pushdown(x); rs(x) = merge(rs(x), y); return pushup(x), x; }else{ pushdown(y); ls(y) = merge(x, ls(y)); return pushup(y), y; } } inline int newnode(int a, int b){ t[++tot].x = a, t[tot].y = t[tot].val = b, t[tot].wei = rand(); return tot; } } using namespace FHQ_treap; int main(){ n = read(); for(int i = 1; i <= n; ++i) S[i] = read(), T[i] = read(); int ans = 0, a, b, c; root = newnode(0, 0); for(int i = n; i >= 1; --i){ split_pos(root, S[i], a, b); int res = t[a].val + S[i] + T[i]; ans = max(ans, res); t[a].tag++, t[a].x--, t[a].y++, t[a].val++;//奶牛初始坐标向左依次减 1,对于 (a, b) 来说相当于变成了 (a - 1, b) split_val(b, res + 1 - S[i], b, c); root = merge(a, merge(newnode(S[i], res + 1 - S[i]), c)); } write(ans), puts(""); return 0; }
- 1
信息
- ID
- 2167
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者