先思考50分的做法。
显然是拆式子,把和i有关的划到一边,和j有关的划到一边,中间有个-ij,维护一个交点递减的单调栈,直接做就好了(斜率优化什么的我不会)。
100分的做法比较坑爹。
对于x,首先预处理不选它的最大值,用50分的做法前后做两遍就行了。
还要求出一定选它的最大值,这就比较玄乎了。
关于区间的,可以yy出分治。
对于区间[x..y],设 m = x +y/ 2
可以对[m+1..y]先做出单调栈。
接着顺序地从x到m扫,维护前缀max,这样可以求出x..m经过这些点并且经过m的区间的最大值并打在上面,发现对于[m+1..y]的还没有做,此时倒着再扫一遍即可。
接着分治,感觉十分的巧,不管怎样,就是这么做了。
Code:
#include
#include
#define ll long long
#define fo(i, x, y) for(ll i = x; i <= y; i ++)
#define fd(i, x, y) for(ll i = x; i >= y; i --)
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const ll N = 6e5 + 5;
ll n, m, x, y;
ll a[N], s[N], f[N], z[N], d[N], c[N], g[N], z0;
double ji(ll x, ll y, ll u, ll v) {
return (double)(y - v) / (double)(u - x);
}
double jx(ll x) {
return ji(-z[x - 1], d[z[x - 1]], -z[x], d[z[x]]);
}
void Solve(ll *f) {
z0 = 0;
fo(i, 1, n) s[i] = s[i - 1] + a[i];
f[1] = max(0, 1 - a[1]); d[1] = f[1] + s[1]; z[++ z0] = 1;
fo(i, 2, n) {
f[i] = f[i - 1];
f[i] = max(f[i], i * (i + 1) / 2 - s[i]);
ll ans = 1;
for(ll l = 2, r = z0; l <= r; ) {
ll m = l + r >> 1;
if(jx(m) >= i)
ans = m, l = m + 1; else r = m - 1;
}
f[i] = max(f[i], d[z[ans]] - z[ans] * i - s[i] + i * (i + 1) / 2);
d[i] = f[i] + s[i] + i * (i - 1) / 2;
while(z0 > 1 && jx(z0) < ji(-z[z0], d[z[z0]], -i, d[i])) z0 --;
z[++ z0] = i;
}
}
void dg(int x, int y) {
if(x == y) return;
int m = x + y >> 1;
z0 = 1; z[1] = m + 1;
d[m + 1] = g[m + 2] - s[m + 1] + (m + 1) * (m + 2) / 2;
fo(i, m + 2, y) {
d[i] = g[i + 1] - s[i] + i * (i + 1) / 2;
while(z0 > 1 && jx(z0) < ji(-z[z0], d[z[z0]], -i, d[i])) z0 --;
z[++ z0] = i;
}
ll mx = -1e18; int r = z0;
fo(i, x - 1, m) {
c[i] = max(c[i], mx);
while(r > 1 && d[z[r]] - i * z[r] < d[z[r - 1]] - i * z[r - 1]) r --;
mx = max(mx, f[i] + s[i] - i * (i - 1) / 2 - i * z[r] + d[z[r]]);
}
z0 = 1; z[1] = x - 1;
d[x - 1] = f[x - 1] + s[x - 1] - (x - 1) * (x - 2) / 2;
fo(i, x, m) {
d[i] = f[i] + s[i] - i * (i - 1) / 2;
while(z0 > 1 && jx(z0) < ji(-z[z0], d[z[z0]], -i, d[i])) z0 --;
z[++ z0] = i;
}
mx = -1e18; r = 1;
fd(i, y, m + 1) {
while(r < z0 && d[z[r]] - z[r] * i < d[z[r + 1]] - z[r + 1] * i) r ++;
mx = max(mx, d[z[r]] - z[r] * i + g[i + 1] - s[i] + i * (i + 1) / 2);
c[i] = max(c[i], mx);
}
dg(x, m); dg(m + 1, y);
}
int main() {
freopen("genocide.in", "r", stdin);
freopen("genocide.out", "w", stdout);
scanf("%lld", &n);
fo(i, 1, n) scanf("%lld", &a[i]);
Solve(f);
fo(i, 1, n / 2) swap(a[i], a[n - i + 1]);
Solve(g);
fo(i, 1, n / 2) swap(g[i], g[n - i + 1]);
fo(i, 1, n / 2) swap(a[i], a[n - i + 1]);
fo(i, 1, n) s[i] = s[i - 1] + a[i];
fo(i, 1, n) c[i] = 1 - a[i];
dg(1, n);
for(scanf("%lld", &m); m; m --) {
scanf("%lld %lld", &x, &y);
printf("%lld\n", max(f[x - 1] + g[x + 1], c[x] + a[x] - y));
}
}