蓝桥杯2024年第十五届省赛真题-拔河(前缀和)

1.题目

原题链接:

c语言网—拔河

题目描述:

小明是学校里的一名老师,他带的班级共有 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)
在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值