首先这道题的一个坑点就是求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,但实际上他们是相互独立的,题目隐晦的告诉这点了,还是理解能力太差了
标签:二分,973,题意,ll,Codeforces,mid,num,Div,这道题 From: https://www.cnblogs.com/-zzuxx-/p/18442947