【JZOJ4805】ksum

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);
        }
    }
}
posted @ 2016-10-10 20:29  sadstone  阅读(35)  评论(0编辑  收藏  举报