Description
给一个长度为 (n) 的序列,任意移动一个数,使得 (sum a[i] imes i) 最大。
(2le nle 2 imes 10^5,left|a[i] ight|le 10^6)
Solution
考虑不移动时答案为 (ans) ,进行一次移动后答案为 (ans') 。
考虑固定 (x) ,枚举从 (x) 移动向 (y(yge x)) ( (y<x) 时同理):
[ans' = ans + a[x] imes y - a[x] imes x - (sum[y] - sum[x])
]
整理一下
[ans'=ans+(sum[x] - a[x] imes x) + (a[x] imes y - sum[y])
]
把与 (x) 相关的看为常数,定义
[f(y)=a[x] imes y - sum[y]
]
这玩意儿是凸的,所以可以三分最高点了。
#include<bits/stdc++.h>
using namespace std;
template <class T> inline void read(T &x) {
x = 0; bool flag = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == 45) flag = 1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48; if (flag) x = -x;
}
#define N 200010
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define ll long long
int n;
ll a[N], sum[N], tot;
inline ll calc(int x, int y) {
if (x <= y) return tot + a[x] * (y - x) - (sum[y] - sum[x]);
return tot + a[x] * (y - x) + (sum[x - 1] - sum[y - 1]);
}
int main() {
read(n);
rep(i, 1, n) read(a[i]), sum[i] = sum[i - 1] + a[i], tot += i * a[i];
ll ans = -(1ll << 62);
rep(i, 1, n) {
int l = 1, r = n;
ll cur = -(1ll << 62);
while (l <= r) {
int mid1 = l + (r - l) / 3, mid2 = r - (r - l) / 3;
ll ans1 = calc(i, mid1), ans2 = calc(i, mid2);
if (ans1 > ans2) r = mid2 - 1, cur = max(cur, ans1);
else l = mid1 + 1, cur = max(cur, ans2);
}
ans = max(ans, cur);
}
cout << ans;
return 0;
}