题解:P5978 [CEOI 2018] Global warming
weilycoder · · 题解
第一眼的思路肯定是把序列分成
然后注意到,对于这样一个方案,如果把最后一段
再贪心一下发现第二段直接加
最长上升子序列的求法参考 P1020 导弹拦截。
总之我们可以求出两个数组
然后从前往后扫一遍,对于每个位置
随便用数据结构维护一下就行了。
:::success[Code]
#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;
}
:::