【JZOJ4805】ksum

本文介绍了一种求解给定正整数数组中前k大的连续子数组和的算法。该方法通过使用优先级队列(堆)来维护当前最大的子数组和,并通过不断取出最大值并更新队列来找到所有前k大的连续子数组和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

给你一个n个数的数组,输出前k大的连续字段和。数组元素为正。

Solution

首先,最大肯定是全部加起来。

我们先把[1,n]扔进堆。

每次操作把最大的区间[l,r]取出来输出,扔出堆,然后把[l,r1][l+1,r]扔进堆里。

但我们发现会有重复,于是只有当r=n时我们才把[l+1,r]扔进堆里。

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<queue>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100001
#define ll long long
using namespace std;
struct node{
    friend bool operator< (node x,node y)
    {
        return x.v<y.v;
    }
    ll v;
    int l,r;
};
priority_queue<node> q;
ll a[N],s[N];
int main()
{
    freopen("ksum.in","r",stdin);
    freopen("ksum.out","w",stdout);
    int n,k;
    cin>>n>>k;
    fo(i,1,n)
    {
        scanf("%lld",&a[i]);
        s[i]=s[i-1]+a[i];
    }
    node p;
    p.v=s[n];
    p.l=1;
    p.r=n;
    q.push(p);
    fo(i,1,k)
    {
        printf("%lld ",q.top().v);
        node p1=q.top(),p2=p1;
        q.pop();
        if(p1.r==n && p1.l<p1.r)
        {
            p1.v-=a[p1.l];
            p1.l++;
            q.push(p1);
        }
        if(p2.l<p2.r)
        {
            p2.v-=a[p2.r];
            p2.r--;
            q.push(p2);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值