题解
诶…比赛的时候写崩了…
题意:
有一种计算区间的方式:
s
u
m
(
l
,
r
)
sum(l,r)
sum(l,r)表示区间
[
l
,
r
)
[l,r)
[l,r)里的数字之和,
现在往区间里插入三个点
d
1
,
d
2
,
d
3
d_1,d_2,d_3
d1,d2,d3,且允许点重合,
问
s
u
m
(
0
,
d
1
)
−
s
u
m
(
d
1
,
d
2
)
+
s
u
m
(
d
2
,
d
3
)
−
s
u
m
(
d
3
,
n
)
sum(0,d_1)-sum(d_1,d_2)+sum(d_2,d_3)-sum(d_3,n)
sum(0,d1)−sum(d1,d2)+sum(d2,d3)−sum(d3,n)的最大值
第一反应前缀和,
然后看看数据,应该最多两个for,暴力枚举两个端点d1、d3,在d1、d3之间找d2,而因为d3是一位一位移动的,所以可以找区间里面前缀和小的作为端点d2,根据公式找最大就行了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
int n, m, k, d1, d2, d3;
ll sum[N];
ll cal(int l, int r) {
return sum[r - 1] - sum[l - 1];
}
int main() {
ios::sync_with_stdio(0);
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> sum[i];
sum[i] += sum[i - 1];
}
ll ans = -(1ll << 60);
for (int i = 0; i <= n; ++i) {
ll tmp = sum[i];
int pos = i;
for (int j = i; j <= n; ++j) {
if (sum[j] < tmp) {
pos = j;
tmp = sum[j];
}
ll Sum = cal(1, i + 1) - cal(i + 1, pos + 1) + cal(pos + 1, j + 1) - cal(j + 1, n);
if (Sum >= ans) {
d1 = i;
d2 = pos;
d3 = j;
ans = Sum;
}
}
}
printf("%d %d %d\n", d1, d2, d3);
return 0;
}