专栏文章

题解:P5978 [CEOI 2018] Global warming

P5978题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minacd3n
此快照首次捕获于
2025/12/01 23:09
3 个月前
此快照最后确认于
2025/12/01 23:09
3 个月前
查看原文
第一眼的思路肯定是把序列分成 33 段:[1,l),[l,r],(r,n][1,l),[l,r],(r,n]。然后从三段中各取一个最长上升子序列拼起来。
然后注意到,对于这样一个方案,如果把最后一段 (r,n](r,n] 也加上 dd,显然答案不会下降。因此实际上只需要把序列分成 22 段,分别求最长上升子序列拼起来。
再贪心一下发现第二段直接加 xx 不劣的。
最长上升子序列的求法参考 P1020 导弹拦截
总之我们可以求出两个数组 ppsspip_i 表示以第 ii 个元素结尾时的最长上升子序列长度,sis_i 表示以第 ii 个元素开头时的最长上升子序列长度。
然后从前往后扫一遍,对于每个位置 ii,计算 si+maxj<i,aj<ai+xpjs_i+\max\limits_{j\lt i,a_j\lt a_i+x} p_{j} 即可。
随便用数据结构维护一下就行了。
CodeCPP
#include <bits/stdc++.h>
using namespace std;

template <typename T, typename Compare = less<T>> class LongestIncreasingSubsequence {
public:
  vector<size_t> last;

  LongestIncreasingSubsequence(size_t size, const T &maxx, const T &minn) : last(size + 1, maxx) {
    last[0] = minn;
  }

  size_t insert(const T &value) {
    constexpr Compare comp{};
    auto it = lower_bound(last.begin(), last.end(), value, comp);
    *it = value;
    return distance(last.begin(), it);
  }
};

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  cin.exceptions(cin.failbit | cin.badbit);

  size_t n;
  int64_t x;
  cin >> n >> x;

  vector<int64_t> arr(n);
  for (size_t i = 0; i < n; ++i)
    cin >> arr[i];

  vector<size_t> suffix(n);
  {
    LongestIncreasingSubsequence<int64_t, greater<int64_t>> LIS(n, INT64_MIN, INT64_MAX);
    for (size_t i = n - 1; ~i; --i)
      suffix[i] = LIS.insert(arr[i]);
  }

  size_t ans = suffix[0];
  multiset<pair<int64_t, size_t>> last;
  LongestIncreasingSubsequence<int64_t> LIS(n, INT64_MAX, INT64_MIN);
  for (size_t i = 1; i < n; ++i) {
    {
      size_t len = LIS.insert(arr[i - 1]);
      auto it = last.emplace(arr[i - 1], len);
      pair<int64_t, size_t> curr = *it;
      for (++it; it != last.end(); it = last.erase(it))
        if (it->second > curr.second)
          break;
    }
    {
      auto it = last.lower_bound({arr[i] + x, 0});
      if (it == last.begin())
        continue;
      --it;
      ans = max(ans, it->second + suffix[i]);
    }
  }
  cout << ans << '\n';
  return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...