专栏文章
题解:P5978 [CEOI 2018] Global warming
P5978题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minacd3n
- 此快照首次捕获于
- 2025/12/01 23:09 3 个月前
- 此快照最后确认于
- 2025/12/01 23:09 3 个月前
第一眼的思路肯定是把序列分成 段:。然后从三段中各取一个最长上升子序列拼起来。
然后注意到,对于这样一个方案,如果把最后一段 也加上 ,显然答案不会下降。因此实际上只需要把序列分成 段,分别求最长上升子序列拼起来。
再贪心一下发现第二段直接加 不劣的。
最长上升子序列的求法参考 P1020 导弹拦截。
总之我们可以求出两个数组 和 : 表示以第 个元素结尾时的最长上升子序列长度, 表示以第 个元素开头时的最长上升子序列长度。
然后从前往后扫一遍,对于每个位置 ,计算 即可。
随便用数据结构维护一下就行了。
Code
CPP#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 条评论,欢迎与作者交流。
正在加载评论...