LGBT学分块
题目
【题目描述】
LGTB最近在学分块,但是他太菜了,分的块数量太多他就混乱了,所以只能分成3块
今天他得到了一个数组,他突然也想把它分块,他想知道,把这个数组分成3块,块可以为空,使得3块分块的中的最大值最小
请输出分完之后3块中和的最大值
【输入输出格式】
输入格式:
输入第一行包含一个整数n 代表数组大小
接下来n 个整数(a_1, a_2, ..., a_n),代表数组
对于40% 的数据,(1=<n<= 10)
对于70% 的数据,(1=<n<=10^3)
对于100% 的数据,(1=<n<=10^5, 1=<a_i<=10^7)
输出格式:
输出包含1 个整数,代表分块完成后3 块中的最大值
【输入输出样例】
输入样例#1:
5
9 9 8 7 6
输出样例#1:
17
思路
题目大意:
把一个数组分成三部分(每一部分可空),使得三个部分和的最大值最小,输出这个最小的最大值。(有点绕...仔细理解一下)
大致思路
枚举第一个断点,二分确定第二个断点,让后两个块尽量接近,这样就可以保证两个之中的较大者尽量不会超过第一个块。二分出来后,答案会在那个断点的左右(保险)。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
#define FILE freopen("divide.in","r",stdin);freopen("divide.out","w",stdout);
using namespace std;
const int maxn=100000+5;
LL n,a[maxn],sum[maxn]= {0};
LL ans=0x7f7f7f7f7f7f7f;
inline LL ErFen(LL left,LL right,LL i) {
while(left+1<right) {
LL mid=(left+right)>>1;
if(sum[mid]-sum[i]>sum[n]-sum[mid])
right=mid;
else
left=mid;
}
return left;
}
int main() {
ios::sync_with_stdio(false);
// FILE;
cin>>n;
for(LL i=1; i<=n; i++) {
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
if(n==1) {
cout<<sum[1]<<endl;
return 0;
}
if(n==2) {
cout<<max(sum[1],sum[2])<<endl;
return 0;
}
for(LL i=0; i<n; i++) {
LL final=ErFen(i+1,n,i);
ans=min(ans,max(sum[i]-sum[0],
max(sum[final]-sum[i],
sum[n]-sum[final])));
ans=min(ans,max(sum[i]-sum[0],
max(sum[final+1]-sum[i],
sum[n]-sum[final+1])));
}
cout<<ans;
return 0;
}