题解:UOJ187 【UR 13】Ernd

题解:UOJ187 【UR 13】Ernd

题目描述

“简要来讲,你有一个盘子,时刻 \(0\) 时你可以把盘子放到数轴上的任何一个整数坐标处,接着每一时刻你可以把盘子往左移动一个单位、往右移动一个单位或者不动。接着系统生成了 \(n\) 个水果,第 \(i\) 个水果会在第 \(b_i\) 时刻出现在 \(a_i\) 坐标处,保证 \(b_i\) 单调递增。如果你的盘子在 \(b_i\) 时刻恰好出现在 \(a_i\) 处,那么就能接到这个水果。”

“最后一个水果落下后,游戏结束。分数用这个方式计算,定义变量 \(K\),最开始 \(K\)\(0\),按照顺序考虑每一个水果,如果你接到了当前水果,那么把 \(K\) 加一,否则你的得分将加上 \(K^2\) 并将 \(K\) 清零,游戏结束后你的得分还会加上游戏结束时的 \(K^2\)。即你的得分是每一段连续接到水果的极长区间的长度平方和。”

计算双方可以拿到的最高分。

对于所有数据,\(1\leq n\leq5\times10^5\)\(1\leq a_i,b_i\leq10^9\)

时间限制:\(2\texttt{s}\)

空间限制:\(128\texttt{MB}\)

题解

由于本题是求最值,那么这个 \(K^2\) 大概率只能用斜率优化攻击了,拆不掉。

先搞一点暴力做法。仔细整理,我们可以令 \(f_i\) 表示最后一个连续段的开始为 \(i\),结尾未定;\(g_i\) 表示最后一个连续段的结尾为 \(i\),最后一段的分数已经计算。则它们可以互相转移:

\[g_i=\max_{j\leq i, chk([j,i])}\left( f_j+(i-j+1)^2\right) \]

\[f_i=\max_{j<i, chk(\{j, i\})}g_i \]

\(chk(S)\) 表示 \(S\) 这个集合是否可以全部接到。我们发现在这个暴力中 \(g_i\) 比较简单,因为合法的 \(j\) 一定在某个 \([lim_i, i]\) 之间,而且会有一个分段的感觉,只有同段的位置可以互相转移。\(f_i\) 就比较逆天了,\(chk(\{j,i\})=[b_i-b_j\geq |a_i-a_j|]\),拆出来有两个维度,是动态二维偏序。本题数据范围太大了,直接跑动态二维偏序肯定过不了。就没有其它办法了吗?

我们把偏序条件写出来:

  • \(b_j+a_j\leq b_i+a_i\)
  • \(b_j-a_j\leq b_i-a_i\)

注意到,当这两个偏序条件都被满足时,\(b_j\leq b_i\) 会自动满足,从而 \(j<i\) 会自动满足。有一个维度消失了!

但这样就会面临一个问题,假设我们按照 \(b_j-a_j\) 排序拆掉第二维偏序,则 \(f\) 可以用树状数组优化转移,但是 \(g\) 这边就爆炸了,因为 \(g\) 需要按照 \(j\) 的顺序转移,\(j\) 不是连续的。

我们回想起 \(g_i\) 的转移隐含一个分段的过程。由于每一个段在排序后的新序列会保留其中的顺序(这是显然的,因为它们可以互相转移),我们对于排序后的 \(g_i\),直接记录它属于原来的哪个段,最后 DP 的时候,每个段都维护一个斜率优化的凸包就可以了。

复杂度 \(O(n\log n)\)

代码

#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define endl "\n"
#define debug(...) void(0)
#endif
using LL = long long;
constexpr int N = 5e5 + 10;
template <class T>
struct flower {
  vector<T> vec;
  flower& operator<<(const T& x) {
    vec.push_back(x);
    return *this;
  }
  int build() {
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    return vec.size();
  }
  T operator[](int i) const { return vec[i - 1]; }
  int operator()(const T& x) const {
    return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1;
  }
};
flower<int> hua;
template <int N>
struct fenwick {
  LL t[N];
  fenwick() { memset(t, ~0x3f, sizeof t); }
  void add(int p, LL k) { for (; p < N; p += p & -p) t[p] = max(t[p], k); }
  LL qry(int p, LL r) { for (; p > 0; p -= p & -p) r = max(r, t[p]); return r; }
};
struct node {
  int x, y, id;
} a[N];
LL f[N], g[N];
struct dot {
  LL x, y;
};
dot get(int i) { return {2 * (a[i].id - 1), f[i] + 1ll * (1 - a[i].id) * (1 - a[i].id)}; }
dot operator-(dot lhs, dot rhs) { return {lhs.x - rhs.x, lhs.y - rhs.y}; }
LL cross(dot lhs, dot rhs) {
  return lhs.x * rhs.y - lhs.y * rhs.x;
}
struct convex {
  vector<int> q;
  void clear() { q.clear(); }
  void push_back(int i) {
    while (q.size() > 1 && cross(get(i) - get(q.back()), get(q.end()[-2]) - get(q.back())) >= 0) q.pop_back();
    q.push_back(i);
  }
  LL qry(int k) {
    while (q.size() > 1 && cross(get(q.back()) - get(q.end()[-2]), dot{1, k}) > 0) q.pop_back();
    if (q.empty()) return -1e18;
    auto res = get(q.back());
    return res.y - k * res.x;
  }
};
fenwick<N * 2> tr;
int n;
int main() {
#ifndef LOCAL
  cin.tie(nullptr)->sync_with_stdio(false);  
#endif
  cin >> n;
  for (int i = 1, x, y; i <= n; i++) cin >> x >> y, a[i] = {y - x, y + x, i}, hua << a[i].y;
  hua.build();
  sort(a + 1, a + n + 1, [&](auto lhs, auto rhs) { return lhs.x != rhs.x ? lhs.x < rhs.x : lhs.y < rhs.y; });
  static int nid[N], lst[N];
  for (int i = 1; i <= n; i++) {
    nid[a[i].id] = i;
  }
  for (int i = 1; i <= n; i++) {
    int j = nid[a[i].id - 1];
    if (a[j].x <= a[i].x && a[j].y <= a[i].y) lst[i] = lst[j], assert(j < i);
    else lst[i] = i;
  }
  static convex conv[N];
  for (int i = 1; i <= n; i++) {
    debug("(%d, %d)\n", a[i].x, a[i].y);
    f[i] = tr.qry(hua(a[i].y), 0);
    auto &c = conv[lst[i]];
    c.push_back(i);
    g[i] = c.qry(a[i].id) + 1ll * a[i].id * a[i].id;
    tr.add(hua(a[i].y), g[i]);
    debug("f[%d] = %lld, g[%d] = %lld\n", i, f[i], i, g[i]);
  }
  cout << *max_element(g + 1, g + n + 1) << endl;
  return 0;
}

posted @ 2025-09-26 10:55  caijianhong  阅读(73)  评论(0)    收藏  举报