【NOIP2016提高A组五校联考4】ksum

3 篇文章 0 订阅

Description

这里写图片描述

Solution

这题不是明显的堆来模拟吗,然后在hash判个重就好了。
但是,这题要值得反思的是,我以前的人工堆有一个很致命的错误,就是堆顶退堆的时候,应该把堆底和堆顶交换,然后num–之后再down一下,这然才对,错误的就不说了。
还有一个问题就是:我不会用STL来实现多元的堆,这个还要学习一下。

Code

#include<iostream>
#include<cstdio>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll maxn=100007,mo=10000007;
ll i,j,k,t,n,m,ans,tot,shu;
ll a[maxn],l[maxn],r[maxn],sum[maxn];
ll h[mo];
bool hash(ll x,ll y){
    ll o=(maxn*maxn%mo*x%mo+maxn*y%mo)%mo;
    while(h[o]!=x&&h[o]!=0)o=(o+1)%mo;
    if(!h[o]){h[o]=x;return 1;}
    return 0;
}
void up(ll x){
    while(x>1&&sum[x]>sum[x/2]){
        swap(sum[x],sum[x/2]),swap(l[x],l[x/2]),swap(r[x],r[x/2]);
        x/=2;
    }
}
void down(ll x){
    while(x*2<=tot&&sum[x*2]>sum[x]||x*2+1<=tot&&sum[x*2+1]>sum[x]){
        ll y=x*2;
        if(y+1<=tot&&sum[x*2+1]>sum[x*2])y++;
        swap(sum[x],sum[y]),swap(l[x],l[y]),swap(r[x],r[y]);
        x=y;
    }
}
int main(){
    freopen("ksum.in","r",stdin);
    freopen("ksum.out","w",stdout);
    scanf("%d%d",&n,&k);
    fo(i,1,n)scanf("%d",&a[i]),t+=a[i];
    sum[++tot]=t,l[tot]=1,r[tot]=n;
    while(k--){
        printf("%lld ",sum[1]);
        if(l[1]==r[1]){
            swap(sum[1],sum[tot]);swap(l[1],l[tot]);
            swap(r[1],r[tot]);tot--;down(1);
            continue;
        }
        if(hash(l[1]+1,r[1])){
            sum[++tot]=sum[1]-a[l[1]];
            l[tot]=l[1]+1,r[tot]=r[1];
            up(tot);
        }
        if(hash(l[1],r[1]-1)){
            sum[++tot]=sum[1]-a[r[1]];
            l[tot]=l[1],r[tot]=r[1]-1;
            up(tot);
        }
        swap(sum[1],sum[tot]);swap(l[1],l[tot]);
        swap(r[1],r[tot]);tot--;down(1);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值