题目来源:https://atcoder.jp/contests/abc102/tasks/arc100_b?lang=en
//
题意:将一串数字分为四段,求出每段的总和,怎么分,才能让这四段的各自总和的极差最小?
//
思路:“实在是想不出来好的算法,只会暴力,当时想的枚举中间的那一刀,然后左右二分,但是感觉也不太好写,毕竟我总是被二分的边界恶心”,题解一看,居然能有O(n)的算法,实在是太优美。
里面是有思维优化的,要让极差最小,无非就是把这四段分的均匀点。这个很重要啊,然后也是枚举中间的j变量,枚举一次,左边和右边i和k,就让各自的两段分均匀。
用的前缀和来比较的,注意:
//
//
//
右边的k同理
//
//
题解代码:
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+9;
int Min=INT64_MAX;
vector<int>a(N,0);
signed main() {
int n, num;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> num;
a[i] += a[i - 1] + num;
}
for (int i = 1, j = 2, k = 3; j < n; ++j) {
while (i + 1 < j && abs(a[j] - 2 * a[i]) > abs(a[j] - 2 * a[i + 1])) ++i;
while (k + 1 < n && abs(a[n] + a[j] - 2 * a[k]) > abs(a[n] + a[j] - 2 * a[k + 1])) ++k;
Min = min(Min, max({a[i], a[j] - a[i], a[k] - a[j], a[n] - a[k]})- min({a[i], a[j] - a[i], a[k] - a[j], a[n] - a[k]}));
}
cout << Min << endl;
return 0;
}