题意
给出n和x,还有一个大小为n的序列a。
让你选取一个区间[l,r],让al..ra_{l..r}al..r都加上d(∣d∣≤x)(|d|\leq x)(∣d∣≤x),最大化a的LIS。
思路
如果在[l,r]加上d,不如在[l,n]加上d,并不会使答案更劣。
证:因为在[l,r]加上d,增加的LIS肯定从前面转移过来,[r+1,n]同时加的话,不会使答案更劣。
d≥0d\geq0d≥0,因为d<0d<0d<0可以转化成d≥0d\geq0d≥0(减操作相当于在后面做加操作)。
所以d=xd=xd=x,对答案没有影响。
故枚举一个中间点,合并一下到i未加x的LIS和i到加x的LIS。
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
int n, x, cnt, ans;
int a[200001], f[200001], g[200001];
int main() {
file(glo);
scanf("%d %d", &n, &x);
for (int i = 1; i <= n; i++)
scanf("%d", a + i);
for (int i = 1, pos; i <= n; i++) {
g[i] = std::lower_bound(f + 1, f + cnt + 1, a[i] + x) - f - 1;
pos = std::lower_bound(f + 1, f + cnt + 1, a[i]) - f;
f[pos] = a[i];
cnt = std::max(cnt, pos);
}
cnt = 0;
for (int i = n, pos; i >= 1; i--) {
pos = std::lower_bound(f + 1, f + cnt + 1, a[i], std::greater<int>()) - f;
f[pos] = a[i];
cnt = std::max(cnt, pos);
ans = std::max(ans, g[i] + pos);
}
printf("%d", ans);
}