当前位置: 首页 > article >正文

蓝桥杯 之 拔河(2024年C/C++ B组 H题)

文章目录

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 本题是 2024年C/C++ B组的H题
  • 首先看这个数据范围,个数也就在10^3,并且考察的还是连续区间的和的最小差值位置,注意的是这个区间是不能重合的
    • 连续区间和的问题,考虑用到这个前缀和
    • 由于考察的是左右两个区间,并且还不能重合,所以得考虑使用这个双指针,通过枚举左右区间的左右端点进行求解
    • 处理的细节:得使用一个列表存储每一个区间和,使用前缀和,进行两层遍历即可,得到store,然后进行一个升序排序
    • ==》 有一个很巧妙的思路,就是在store数组中,直接遍历相邻的元素,作差,然后直接更新答案在这里,即使有重复的元素,后面也可以进行作差减去,但是这个方法是存在一个问题的,没有处理重复的问题,但是在蓝桥杯官网这边的测试用例hack不掉
    • 正宗的做法是,逐步删除重合的区间,通过二分查找,找到最接近的区间和,进行作差,更新答案

下面的python的代码,作者自己写的,和官方的题解的差别在于这个下标是从0开始

import bisect
# 总体来说就是使用这个双指针进行暴力求解

n = int(input())
a = list(map(int, input().split()))

store = []
pre = [0]*(n+1)
for i in range(n):
  pre[i+1] = pre[i] + a[i]
# 求解前缀和的全部组合
# 这个l,r对应的是下标,
for l in range(n):
  for r in range(l,n):
    cur = pre[r+1] - pre[l]
    store.append(cur)
# 排个序
store = sorted(store)

res = float('inf')

# 现在开始双指针暴力枚举
# 枚举这个 左边队伍的右端点
for r1 in range(n):
  # 首先得将右边区间的以r1为左端点的值从这个store中去掉
  for l2 in range(r1,n):
    diff = pre[l2+1] - pre[r1]
    index = bisect.bisect_left(store,diff)
    if index < len(store) and store[index] == diff:
      store.pop(index)
  # 现在就开始枚举这个左边区间的左端点
  for l1 in range(r1+1):
    target = pre[r1+1] - pre[l1]
    index = bisect.bisect_left(store,target)
    if index < len(store):
      res = min(res,abs(target-store[index]))
    if index > 0:
      res = min(res,abs(target-store[index-1]))
print(res)

下面展示官方的题解

在这里插入图片描述
在这里插入图片描述

  • C++
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
ll a[N], sum[N];
multiset<ll>se;
int main(){
    int n; cin >> n;
    for(int i = 1 ; i <= n ; i ++) cin >> a[i], sum[i] = sum[i - 1] + a[i];
    for(int i = 1 ; i <= n ; i ++) for(int j = i ; j <= n ; j ++){
        se.insert(sum[j] - sum[i - 1]);
    }
    se.insert(-INF);
    se.insert(INF);
    ll res = LONG_MAX;
    for(int i = 1 ; i <= n ; i ++){
        for(int r = i ; r <= n ; r ++){
            auto it = se.find(sum[r] - sum[i - 1]);
            se.erase(it);
        }
        for(int l = 1 ; l <= i ; l ++){
            auto x = se.lower_bound(sum[i] - sum[l - 1]);
            res = min(res, abs(sum[i] - sum[l - 1] - *x));
            x --;
            res = min(res, abs(sum[i] - sum[l - 1] - *x));
        }
    }
    cout << res << '\n';
    return 0;
}
  • Java
import java.util.*;

public class Main {
    static final long INF = Long.MAX_VALUE;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        long[] a = new long[n + 1];
        long[] sum = new long[n + 1];
        TreeSet<Long> set = new TreeSet<>();

        for (int i = 1; i <= n; i++) {
            a[i] = scanner.nextLong();
            sum[i] = sum[i - 1] + a[i];
        }

        for (int i = 1; i <= n; i++) {
            for (int j = i; j <= n; j++) {
                set.add(sum[j] - sum[i - 1]);
            }
        }

        set.add(-INF);
        set.add(INF);

        long res = Long.MAX_VALUE;
        for (int i = 1; i <= n; i++) {
            for (int r = i; r <= n; r++) {
                long diff = sum[r] - sum[i - 1];
                set.remove(diff);
            }
            for (int l = 1; l <= i; l++) {
                long target = sum[i] - sum[l - 1];
                Long x = set.ceiling(target);
                if (x != null) {
                    res = Math.min(res, Math.abs(sum[i] - sum[l - 1] - x));
                }
                if (x != null && x != set.first()) {
                    x = set.lower(target);
                    res = Math.min(res, Math.abs(sum[i] - sum[l - 1] - x));
                }
            }
        }
        System.out.println(res);
    }
}
  • python
import sys
import bisect

INF = float('inf')

def main():
    input = sys.stdin.read
    data = input().split()
    
    n = int(data[0])
    a = [0] * (n + 1)
    sum = [0] * (n + 1)
    for i in range(1, n + 1):
        a[i] = int(data[i])
        sum[i] = sum[i - 1] + a[i]
    
    set_sum = []
    
    for i in range(1, n + 1):
        for j in range(i, n + 1):
            set_sum.append(sum[j] - sum[i - 1])
    
    set_sum.append(-INF)
    set_sum.append(INF)
    set_sum.sort()
    
    res = INF
    
    for i in range(1, n + 1):
        for r in range(i, n + 1):
            diff = sum[r] - sum[i - 1]
            idx = bisect.bisect_left(set_sum, diff)
            if idx < len(set_sum) and set_sum[idx] == diff:
                set_sum.pop(idx)
        
        for l in range(1, i + 1):
            target = sum[i] - sum[l - 1]
            idx = bisect.bisect_left(set_sum, target)
            if idx < len(set_sum):
                res = min(res, abs(sum[i] - sum[l - 1] - set_sum[idx]))
            if idx > 0:
                res = min(res, abs(sum[i] - sum[l - 1] - set_sum[idx - 1]))
    
    print(res)

if __name__ == "__main__":
    main()

http://www.kler.cn/a/593335.html

相关文章:

  • Leetcode 50.Pow(x,n) 使用快速幂求解
  • Flask从入门到精通--初始Flask
  • 仓库管理不能仅流于形式,需挖掘潜在价值
  • [科普] git和github等是什么关系 (由DS-R1生成)
  • Android SDK下载安装配置
  • 机器学习快速入门教程
  • 栈/堆/static/虚表
  • Fisher 信息矩阵公式原理:使用似然估计,二阶导数等知识点
  • MySQL 在 CentOS 7 上安装的步骤指南
  • Web3身份验证技术对数据保护的影响研究
  • C#入门学习记录(二)C# 中的转义字符——字符串处理的“魔法钥匙”​
  • QT入门笔记3
  • 这样配置让Nginx更安全
  • 服装零售行业数字化时代的业务与IT转型规划P111(111页PPT)(文末有下载方式)
  • iwebsec-SQL数字型注入
  • 基于Babylon.js的Shader入门之五:让Shader支持法线贴图
  • jmeter验证正则表达式提取值是否正确
  • C语言中,memmove和memcpy的区别?
  • 脚本一键式启动Nginx、Mysql、Redis
  • 台式机电脑组装---电脑机箱与主板接线