NOIP提高组【JZOJ4815】ksum

5 篇文章 0 订阅
3 篇文章 0 订阅

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

我们考虑用堆来解决这道题。显然我们维护一个大根堆,每次抽取最大的一个输出,并将他向左向右各移动一位加入堆中,从堆中删除堆顶,不断维护就好了。时间复杂度为O(K logK )。

代码

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const ll maxn=2000007,maxn1=100001,maxn2=maxn*10;
ll l[maxn],r[maxn],a[maxn],d[maxn],h[maxn2];
ll n,i,t,j,k,m,num;
void up(int x){
    while (x>1 && d[x]>d[x/2]){
        swap(d[x],d[x/2]);swap(l[x],l[x/2]);swap(r[x],r[x/2]);
        x/=2;
    }
}
void down(int x){
    int y;
    while (x*2<=num && d[x*2]>d[x] || x*2<num && d[x*2+1]>d[x]){
        y=x*2;
        if (y<num && d[y+1]>d[y]) y++;
        swap(d[x],d[y]);swap(l[x],l[y]);swap(r[x],r[y]);
        x=y;
    }
}
bool hash(ll x,ll y){
    ll z=x*maxn1+y,k=z%maxn2;
    while (h[k]!=z && h[k]){
        k++;
        if (k==maxn2) k=0;
    }
    if (h[k]) return false;
    if (!h[k]) h[k]=z;return true;
}
int main(){
    freopen("ksum.in","r",stdin);freopen("ksum.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)
        scanf("%d",&a[i]),t+=a[i];
    d[++num]=t,l[1]=1;r[1]=n;
    hash(l[1],r[1]);
    while (m){
        printf("%lld ",d[1]);
        if (l[1]<r[1]){
            if (hash(l[1]+1,r[1])){
                d[++num]=d[1]-a[l[1]];
                l[num]=l[1]+1;r[num]=r[1];
                up(num);
            }
            if (hash(l[1],r[1]-1)){
                d[++num]=d[1]-a[r[1]];
                l[num]=l[1];r[num]=r[1]-1;
                up(num);
            }
        }
        d[1]=d[num];l[1]=l[num];r[1]=r[num];num--;
        down(1);
        m--;
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值