CF2055E 题解
Albert_Wei · · 题解
\textup{\textbf{Part 1}}
考虑
\textup{\textbf{Part 2}}
考虑草垛清空顺序确定的情况(不妨设为从
\textup{\textbf{Part 3}}
考虑去掉
- 对于
a_i - b_i \le 0 的部分,有a_x - b_x + a_y \le a_y ,所以只需保证a_x \le a_y ,按照a 从小到大排序即可。 - 对于
a_i - b_i > 0 的部分,有a_x < a_y - b_y + a_x ,所以只需保证a_x - b_x + a_y \le a_y - b_y + a_x ,即b_x \ge b_y ,按照b 从大到小排序即可。\textup{\textbf{Part 4}} 考虑
c_n = 0 的限制,我们发现它要求\sum \limits_{i = 1} ^ n (a_j - b_j) + b_n \le 0 ,即b_n \le \sum \limits_{i = 1} ^ n (b_j - a_j) ,可以预处理出有哪些草垛满足。于是我们只需要考虑去掉一个草垛后对\sum\limits_{j = 1} ^ {i - 1} (a_j - b_j) + a_i 的影响。这只是对该草垛所在位置之后的值做一个后缀减,所以维护前、后缀最大值即可。总复杂度\mathcal{O}(n \log n) ,瓶颈在排序。
核心代码:
n = read(), pos.clear();
sum = tot = 0, pmx[0] = smx[n + 1] = -1e18;
for (int i = 1; i <= n; i ++) {
t[i].a = read(), t[i].b = read();
t[i].dlt = t[i].a - t[i].b, sum -= t[i].dlt, tot += t[i].a;
}
sort(t + 1, t + n + 1, [&](Thing x, Thing y) {
if (x.dlt <= 0 && y.dlt > 0) return true;
if (x.dlt > 0 && y.dlt <= 0) return false;
if (x.dlt <= 0 && y.dlt <= 0) return x.a < y.a;
return x.b > y.b;
});
for (int i = 1; i <= n; i ++)
if (t[i].b <= sum) pos.push_back(i);
if (!pos.size()) return puts("-1"), void();
for (int i = 1; i <= n; i ++) {
val[i] = val[i - 1] + t[i].a - t[i - 1].b;
pmx[i] = max(pmx[i - 1], val[i]);
}
for (int i = n; i >= 1; i --) smx[i] = max(smx[i + 1], val[i]);
LL ans = 1e18;
for (int i : pos) Fmin(ans, max(pmx[i - 1], smx[i + 1] - t[i].a + t[i].b));
cout << max(0ll, ans) + tot << '\n';