Description
![这里写图片描述](https://img-blog.csdn.net/20161010141844544)
Data Constraint
![这里写图片描述](https://img-blog.csdn.net/20161010141859895)
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--;
}
}