1.题目
原题链接:
题目描述:
小明是学校里的一名老师,他带的班级共有 n 名同学,第 i 名同学力量值为 ai。在闲暇之余,小明决定在班级里组织一场拔河比赛。
为了保证比赛的双方实力尽可能相近,需要在这 n 名同学中挑选出两个队伍,队伍内的同学编号连续:{al1, al1+1, …, ar1−1, ar1} 和 {al2, al2+1, …, ar2−1, ar2},其中 l1 ≤ r1 < l2 ≤ r2。
两个队伍的人数不必相同,但是需要让队伍内的同学们的力量值之和尽可能相近。请计算出力量值之和差距最小的挑选队伍的方式。
输入格式
输入共两行。
第一行为一个正整数 n。
第二行为 n 个正整数 ai。
输出格式
输出共一行,一个非负整数,表示两个队伍力量值之和的最小差距。
样例输入:
5
10 9 8 12 14
样例输出:
1
提示:
【样例说明】
其中一种最优选择方式:队伍 1:{a1, a2, a3},队伍 2:{a4, a5},力量值和分别为 10 + 9 + 8 = 27,12 + 14 = 26,差距为 |27 − 26| = 1。
【评测用例规模与约定】
对于 20% 的评测用例,保证 n ≤ 50。
对于 100% 的评测用例,保证 n ≤ 10^3,ai ≤ 10 ^ 9。
2.思路分析
题目是要我们找出两个编号连续的队伍的差值的最小值,因此要找连续区间内的和,当然要用前缀和来做。
2.1 具体做法:
我们需要用一个两重循环把每个区间段的和都找出来,压入一个数组(这里可以直接用结构体数组,也可以用vector,multiset等),具体就是定义i在外层循环,j在内层循环,每次压入[i,j]的力量和,并且不可以判重,随后对数组进行排序,然后两两比较求出最小差值,另外为了防止同一编号的人被比较,我们需要另外把i也一起压进去,只有i不相同的才进行比较。
i相同肯定会有重复的,i不同当j>i2时,也会有重复的,但是其差值必然是定值,就是选i1到i2-1和单独一个i2这种情况。
2.2 时间复杂度分析:
两个for循环是10^6,然后在遍历一遍,也就是百万级别,时间妥妥够用。
2.3 难点分析
主要就是注意连续的编号这个条件,然后想明白如何去遍历每一种情况
3.代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
typedef pair<LL,int> PII;
const int N=1050;
LL s[N],a[N];
int main(){
int n;
cin>>n;
vector<PII>v;
for(int i=1;i<=n;i++) cin>>a[i],s[i]=s[i-1]+a[i];
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
v.push_back({s[j]-s[i-1],i});
}
}
sort(v.begin(),v.end());
LL ans=1e18;
for(int i=0;i<v.size()-1;i++){
if(v[i].second!=v[i+1].second) ans=min(ans,v[i+1].first-v[i].first);
}
cout<<ans<<endl;
return 0 ;
}
AC截图:(70ms)