BZOJ_2151_种树_贪心+堆+链表

摘要:
BZOJ_2151_植树_贪婪+堆城有一个巨大的圆形广场。为了绿化环境和净化空气,市政府决定在圆形广场的外圈种植一圈树木。对于所有数据:m˂=n-1000˂=Ai˂=1000N的大小对于不同的数据是不同的:数据编号n的大小为1301120235212007340132008445142005015201065516201176017286581999999200191999991020020200000。显然,首先有$O(n^2)$暴力,因此您可以在这个问题上获得70分。我们考虑贪婪,每次选择最大的一个删除,同时删除左侧和右侧的。这显然是错误的,因为可能有354个,我更喜欢3+4而不是5。

BZOJ_2151_种树_贪心+堆

Description

A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。

Input

输入的第一行包含两个正整数n、m。第二行n个整数Ai。

Output

输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。

Sample Input

【样例输入1】
7 3
1 2 3 4 5 6 7
【样例输入2】
7 4
1 2 3 4 5 6 7

Sample Output

【样例输出1】
15

【样例输出2】
Error!
【数据规模】
对于全部数据:m<=n;
-1000<=Ai<=1000
N的大小对于不同数据有所不同:
数据编号 N的大小 数据编号 N的大小
1 30 11 200
2 35 12 2007
3 40 13 2008
4 45 14 2009
5 50 15 2010
6 55 16 2011
7 60 17 2012
8 65 18 199999
9 200 19 199999
10 200 20 200000


首先有$O(n^2)$的暴力显然,于是你这道题就可以拿到70分..

我们考虑贪心,每次挑最大的那个删除,同时把左右的也删除,这显然是错的,因为可能有3 5 4,我选3+4要比选5更优。

但是5仍然非常重要,因为你需要同时选2个才可以不选这个5。

于是有了另外一种可以反悔的贪心的思路:每次找最大的并把它两边删除,把这个数修改成它的权值减去两边的权值,其中找最大的用一个堆来维护,找两边的数用链表。

这样就是对的了,因为这相当于我每次都会取出一个数,并且保证每次对答案的贡献增加的最多。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
#define N 200050
int n,m,a[N],kill[N];
struct node {
    int v,p;
    node() {}
    node(int v_,int p_) :
        v(v_),p(p_) {}
    inline bool operator < (const node &x) const {
        return v<x.v;
    }
};
priority_queue<node>q;
int L[N],R[N];
void del(int x) {
    L[R[x]]=L[x];
    R[L[x]]=R[x];
}
int main() {
    // freopen("tree.in","r",stdin);
    // freopen("tree.out","w",stdout);
    scanf("%d%d",&n,&m);
    if(m>n/2) {
        puts("Error!"); return 0;
    }
    int i;
    for(i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        q.push(node(a[i],i)); L[i]=i-1; R[i]=i+1;
    }
    R[n]=1; L[1]=n; int ans=0;
    for(i=1;i<=m;i++) {
        while(!q.empty()&&kill[q.top().p]) q.pop();
        node t=q.top(); q.pop();
        kill[L[t.p]]=kill[R[t.p]]=1;
        a[t.p]=a[L[t.p]]+a[R[t.p]]-a[t.p];
        del(L[t.p]); del(R[t.p]);
        ans+=t.v;
        q.push(node(a[t.p],t.p));
    }
    printf("%d
",ans);
}

免责声明:文章转载自《BZOJ_2151_种树_贪心+堆+链表》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇easyui treegrid 动态展开数据(暂记)Ethernet帧的分析(转)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

字符串解压缩类库(zip、GZIP、QuickLz、snappy、lzf、jzlib)介绍

它旨在提供高压缩速度和合理的压缩比=-1){out.write;}字节[]未压缩=输出。到字节数组();--返回提取字符串的字节数组。介绍使用预先选择的解压缩类库-GZIP压缩字符串=“这是一个用于测试的字符串”;ByteArrayOutputStreamout=新的ByteArray输出流();GZipOutputStreamgout=newGZipOut...

MySQL学习笔记:字符串前后补全0

遇到一个要求:如果位数小于6,则需要使用函数LPAD()和RPAD()自动完成6位。LPAD使用字符串padstr填充并完成左侧的str,直到其长度达到len个字符,并返回str。...

PbootCMS后台增加轮播图自定义分组名称

我们知道,在PbootCMS后台的旋转木马图形模块中,当添加新的旋转木马图时,您不能自己选择组。相反,您可以自动创建组,例如组1、组2和组3。这显然对客户的体验不友好,而且您无法直观地知道在网页的哪个位置使用了旋转木马图。让我们分享一下如何启用PbootCMS后台来添加、删除和修改旋转木马图形组。...

webstorm关闭烦人的eslint语法检查

使用eslint语法检查后,我们发现JS代码中到处都是红线。通过右键菜单中的fixeslint problems选项,我们可以发现页面代码格式完全被eslint包装。只需关闭exlint语法检查。看不见,想不起来。反向关闭不会影响代码开发,但相反,它会影响代码开发。关闭eslint位置:文件--˃设置--˃语言和框架--˃CodeQualityTools--...

(转)JavaScript-性能优化之函数节流(throttle)与函数去抖(debounce)

简单来说,JavaScript性能优化的函数节流和函数去抖动功能节流就是使函数在极短的时间间隔内无法连续调用。下一个函数调用只能在上次函数执行超过指定的时间间隔后进行。对于这两个需求,有两种解决方案:去抖动和节流。Throwle和debouck是解决请求和响应速度不匹配问题的两种解决方案。抛出以相等的间隔执行函数。如果事件在反跳时间间隔t内再次触发,则将再次...

element-ui表格el-table回显时默认全选数据

1、html代码˂el-table-columntype="selection"width="45"...