AtCoder Regular Contest 100 - D - Equal Cut (二分)

题目

题意:

给你一个区间,让你把区间分成连续的4份,他们各自元素总和。【最大的减去最小的】要最小。

问你最小差值。

POINT:

区间为ABCD。

把AB所在的区间称为左区间。CD为右区间。

把左区间尽量分成平均的2分。右区间也一样。

这样枚举n个答案。然后取最小就行了。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 2e5+33;
#define  LL long long

LL a[maxn],b[maxn];

void f(LL a,LL b,LL &Max,LL &Min)
{
	if(a==0||b==0) return;
	Max=max(Max,a);
	Max=max(Max,b);
	Min=min(Min,a);
	Min=min(Min,b);
}

LL ff(LL x,LL be,LL ed)
{
	LL sum=b[ed]-b[be-1];
	LL aim=sum/2+b[be-1];
	LL k=x;
	LL ju=abs(aim-b[x]);
	if(x-1>=be&&ju>abs(aim-b[x-1]))
	{
		ju=abs(aim-b[x-1]);
		k=x-1;
	}
	if(x+1<ed&&ju>abs(aim-b[x+1])){
		k=x+1;
	}
	return k;
}

int main()
{
	LL n;
	scanf("%lld",&n);
	for(LL i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		b[i]=b[i-1]+a[i];
	}
	LL ans=1e18;
	for(LL i=2;i<=n-2;i++){
		LL Max=0;
		LL Min=1e18;
		LL aim=b[i]/2;
		LL to=lower_bound(b+1,b+1+i,aim) - b;
		if(to==i) to--;
		to=ff(to,1,i);
		f(b[to],b[i]-b[to],Max,Min);
		aim=(b[n]-b[i])/2+b[i];
		to=lower_bound(b+i+1,b+n+1,aim) - b;
		if(to==n) to--;
		to=ff(to,i+1,n);
		f(b[to]-b[i],b[n]-b[to],Max,Min);
		ans=min(ans,Max-Min);
	}
	printf("%lld\n",ans);



}

猜你喜欢

转载自blog.csdn.net/mr_treeeee/article/details/81070819