洛谷P1484 种树

题目描述

   cyrcyr今天在种树,他在一条直线上挖了n个坑。这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树。而且由于cyrcyr的树种不够,

他至多会种k棵树。假设cyrcyr有某种神能力,能预知自己在某个坑种树的获利会是多少(可能为负),请你帮助他计算出他的最大获利。

数据范围

对于20%的数据,n<=20。

对于50%的数据,n<=6000。

对于100%的数据,n<=500000,k<=n/2,在一个地方种树获利的绝对值在1000000以内。

解题思路

我们考虑维护一个优先队列,使得其中的数按照严格单调递减的方式排序。  对于初始化而言,我们将每个点的获利放到优先队列中。

在操作中,每次取出堆顶,对于这个堆顶id我们有两个选择,将其加入选择,或者将它的两端都加入选择。不可能存在一种情况使得两端某个单独加入(如果这样两端id才是堆顶)

对于上述操作的实现是这样的,我们先将该点值直接加入总和中,然后将该点两端删去,把该点的值修改为两端值之和减去原来的该点的值,我们考虑以下几种情况

1.val[x]>=val[l[x]]+val[r[x]]

在这种情况下表示选择该点是最优的抉择,再也不可能影响最后总和结果.

2.val[x]<va[l[x]]+val[r[x]].

有两个可能

  A.它在最后排序中位于可以影响结果的位置,表示对于之前做的决定反悔。

  B.反之表示虽然两端和大于该点值,但是选择此点对于后续的影响使结果更优。

附上AC代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define reg register
using namespace std;
const int Maxn=5e5+5;
typedef long long ll;
struct dug{
    int g,val;
    bool operator <(const dug &rhs) const {
        return val<rhs.val;
    }
};
ll ans=0,val[Maxn];
int n,k,fin=0;
bool sbp[Maxn];
priority_queue<dug> q;
int l[Maxn],r[Maxn];
int main(){
    memset(sbp,0,sizeof(sbp));
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;++i){
        l[i]=i-1;
        r[i]=i+1;
        scanf("%lld",&val[i]);    
        q.push((dug){i,val[i]});
    }
    r[0]=1; l[n+1]=n;
    while(k--){
        while(sbp[q.top().g])q.pop();
        dug fr=q.top(); 
        if(q.top().val<0) break;
        q.pop();
        ans+=fr.val;
        int id=fr.g;
        sbp[r[id]]=sbp[l[id]]=1;
        val[id]=val[l[id]]+val[r[id]]-val[id];
        q.push((dug){fr.g,val[id]});
        l[id]=l[l[id]];r[l[id]]=id;
        r[id]=r[r[id]];l[r[id]]=id;
    }
    printf("%lld",ans);
    return 0;
} 

 

转载于:https://www.cnblogs.com/Hadesa/articles/9763109.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值