Codeforces Round 973 (Div. 2) - D题 - 二分

首先这道题的一个坑点就是求max(a[1], a[2], ..., a[n])和求min(a[1], a[2], ..., a[n])是完全独立的,不会相互影响(可能是我读题能力太差,一直卡在这点了。。。)
这道题二分是一种很好想的方法,题中提到max和min,我们就可以想到只要让最大值最小,让最小值最大就可以达到我的目的了,二分的mid就是我们拟定的最大值的最小最小值的最大(非常明显的二分,但赛时我没想出来。。。)当然操作要根据a[i] - 1、a[i + 1] + 1来进行,这样这道题就完成了,接下来放代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll n;
vector <ll> b;
bool check1(ll num){
    //由于a[i] - 1、a[i + 1] + 1的性质
    //所以想要让前面的数a[i]变大,a[i - 1]就要减少,所以从后往前遍历
    for(ll i = n; i > 1; i --){
        if(b[i] < num){
            b[i - 1] -= num - b[i];
        }
    }
    return b[1] >= num;
}
bool check2(ll num){
    //同理从前往后遍历
    for(ll i = 1; i < n; i ++){
        if(b[i] > num){
            b[i + 1] += b[i] - num;
        }
    }
    return b[n] <= num;
}
void slove(){
    cin >> n;
    vector <ll> a(n + 1);
    for(ll i = 1; i <= n; i ++)
        cin >> a[i];
    ll mx = 0, mn = 0;
    ll l = 1, r = 1e12;
    // 最小值最大
    while(l < r){
        b = a;
        ll mid = l + r + 1 >> 1;
        if(check1(mid))
            l = mid;
        else
            r = mid - 1;
    }
    mn = l;
    l = 1, r = 1e12;
    // 最大值最小
    while(l < r){
        b = a;
        ll mid = l + r >> 1;
        if(check2(mid))
            r = mid;
        else
            l = mid + 1;
    }
    mx = l;
    cout << mx - mn << endl;
    return ;
}
int main(){
    ll t;
    cin >> t;
    while(t --){
        slove();
    }
    return 0;
}

最近感觉做题对于题意的把握太差了,要不就是容易假题意,要不就是很长时间才能理解题意,需要加强理解能力,就像是这道题,我一直在纠结max会影响min,但实际上他们是相互独立的,题目隐晦的告诉这点了,还是理解能力太差了

posted @ 2024-10-01 16:31  zzuxx  阅读(16)  评论(0)    收藏  举报