AtCoder Beginner Contest 102 D - Equal Cut 题解

题意

AtCoder Beginner Contest 102 D - Equal Cut
给定一个数组,切3刀把他分成4份。要求求出4份子数组中的最大的数组和-最小的数组和的值最小。

思路

我们可以枚举第二刀,这样就把整个数组分为了 \(L,R\) 两个部分。

如果想要让整体最小,那么第一刀一定尽量让 \(|L_1-L_2|\) 变得更小,也就是两个更加接近。这个过程我们可以用双指针来实现。第三刀的切法同理。每次枚举第二刀的时候,都求一下当前的结果就好。

代码

#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <cstring>
#include <cmath>

#define fi first
#define se second

using namespace std;
using ll = long long;
using pii = pair<int, int>;

const double eps = 1e-4;
const int N = 2e5+10;
ll n, a[N], b[N], res = 1e18;

void update_res() {
    ll minv = 1e18, maxv = 0;
    for(int i=1; i<=4; i++) {
        ll t = a[b[i]] - a[b[i-1]];
        minv = min(minv, t);
        maxv = max(maxv, t);
    }
    res = min(res, maxv-minv);
}

void solve() {
    scanf("%lld", &n);
    for(int i=1; i<=n; i++) {
        scanf("%lld", &a[i]);
        a[i] += a[i-1];
    }
    // b[1..3]表示第1-3刀
    for(b[1] = 1, b[2] = 2, b[3] = 3, b[4] = n; b[2] <= n-2; b[2]++) {
        // 求第一刀 当下一个位置比当前的位置|L1-L2|更小时就++
        while(abs(a[b[1]] - (a[b[2]]-a[b[1]])) > abs(a[b[1]+1] - (a[b[2]] - a[b[1]+1]))) b[1]++;
        // 求第二刀
        while(abs((a[b[3]]-a[b[2]]) - (a[b[4]]-a[b[3]])) > abs((a[b[3]+1]-a[b[2]]) - (a[b[4]]-a[b[3]+1]))) b[3]++;
        update_res();
    }
    printf("%lld\n", res);
}

int main() {
    // multiple case
    // int t; scanf("%d", &t);
    // while(t--) {
    //     solve();
    // }

    // single case
    solve();

    return 0;
}
posted @ 2023-05-17 11:16  1v7w  阅读(18)  评论(0编辑  收藏  举报