Time Limit: 1000ms                     Memory Limit: 128MB

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!

HINT

【数据规模】

对于全部数据:$m<=n<=200000$,$-1000<=Ai<=1000$

[吐槽]

  所以说为啥一开始我想的是dp。。看到数据范围瞬间爆炸qwq

[题解]

  那就考虑贪心咯?每次选最大值

  问题是选完了一个数之后旁边两个不能选然后这个有个连锁反应的感觉。。

  但是我们可以发现在我们选择了一个位置$a_i$之后,可以直接用$a_{i-1} + a_{i+1} - a_i$这一个值来把$a_i$抵消掉

  既然这样,那就可以直接在选了一个数$a_i$之后,把这个数旁边的两个删掉,然后把$a_i$的值改成上面的用来抵消的值

  然后神奇的地方就在于这样改了之后,其实在选的时候也能起到一个连锁反应的效果

  所以就相当于把这个限制条件也变成了一种选数的操作

  那么贪心一下就直接一个优先队列每次选最大就搞定啦

  (讲真好妙啊qwq)

[一些细节]

  好像也不算什么细节吧。。就是实现的时候要开两个数组记录一下前面和后面是谁因为要一直删数所以会变的

  然后就是已经删掉的数要标记一下如果说队头是被删过的数那就继续pop

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=+;
struct data
{
int id,val;
data(){}
data(int x,int y) {id=x,val=y;}
friend bool operator < (data x,data y)
{return x.val<y.val;}
};
priority_queue<data> q;
bool out[MAXN];
int a[MAXN],pre[MAXN],nxt[MAXN];
int n,m,ans;
int prework();
int del(int x); int main()
{
freopen("a.in","r",stdin); int x;
scanf("%d%d",&n,&m);
if (m>n/) {printf("Error!\n");return ;}
for (int i=;i<=n;++i) scanf("%d",a+i),q.push(data(i,a[i]));
prework();
memset(out,false,sizeof(out));
data now;
for (int i=;i<=m;++i)
{
while (out[q.top().id]) q.pop();
now=q.top();q.pop();
ans+=a[now.id];
a[now.id]=a[pre[now.id]]+a[nxt[now.id]]-a[now.id];
del(pre[now.id]);
del(nxt[now.id]);
q.push(data(now.id,a[now.id]));
}
printf("%d\n",ans);
} int prework()
{
for (int i=;i<=n;++i) pre[i]=i-;
for (int i=;i<n;++i) nxt[i]=i+;
pre[]=n; nxt[n]=;
} int del(int x)
{
out[x]=true;
nxt[pre[x]]=nxt[x];
pre[nxt[x]]=pre[x];
}

挫挫滴代码

【bzoj2151】种树的更多相关文章

  1. bzoj2151 种树 双向链表+堆

    2151: 种树 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1151  Solved: 613[Submit][Status][Discuss] ...

  2. BZOJ2151种树——模拟费用流+链表+堆

    题目描述 A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n.并且每个位置都有一个美观度Ai,如果在这 ...

  3. BZOJ2151 种树(贪心+堆+链表/wqs二分+动态规划)

    dp容易想到,但没法进一步优化了. 考虑贪心,每次选出价值最大的物品.但这显然是不对的因为会影响其他物品的选择. 于是考虑加上反悔操作.每次选出一个物品后,将其相邻两物品删除,再将原物品价值变为相邻两 ...

  4. [BZOJ2151] 种树 贪心

    2151: 种树 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1151  Solved: 613[Submit][Status][Discuss] ...

  5. BZOJ2151: 种树

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2151 题解:此题=数据备份.喜闻乐见挂链表. 代码: #include<cstdio&g ...

  6. bzoj1124[POI2008]枪战maf

    这代码快写死我了.....死人最多随便推推结论.死人最少,每个环可以单独考虑,每个环上挂着的每棵树也可以分别考虑.tarjan找出所有环,对环上每个点,求出选它和不选它时以它为根的树的最大独立集(就是 ...

  7. bzoj3502[PA2012]Tanie Linie(最大k区间和)

    题意:给定一个长为n的数列,要求选出最多k个不相交的区间(可以不选),使得选中的数字之和最大.(1<=k<=n<=1000000)分析:首先我们通过预处理对问题做一些简化.原序列中的 ...

  8. WQS二分题集

    WQS二分,一种优化一类特殊DP的方法. 很多最优化问题都是形如“一堆物品,取与不取之间有限制.现在规定只取k个,最大/小化总收益”. 这类问题最自然的想法是:设f[i][j]表示前i个取j个的最大收 ...

  9. 帝都Day4(2)——数据结构

    黄姓dalao is coming! 一.栈: 基本常识略. 例题:铁轨 模拟,O(n), Usaco2006 Nov 题目略 做法:单调栈(续命栈?) n//数量 a[]//奶牛 for(int i ...

  10. 0x17 二叉堆

    优先队列太好用了手写啥呀 poj1456 经过贪心专题的洗礼以后这题根本就不叫题啊...按时间大到小排每次取最大就好 #include<cstdio> #include<iostre ...

随机推荐

  1. 安装kvm模块配置网络

    1. vmware安装centos6.6 64位 (略) 其中有几个注意的地方:a. 内存给2gb. 磁盘给50g, 或者再单独分一个磁盘,用来存储虚拟机文件c. 最关键的一步,在创建虚拟机时,cpu ...

  2. CentOS 挂载 cdrom, iso文件作为源

    在生产系统环境中的机器都没有连接互联网,因此都是使用本地源. 首先,需要将cdrom, 或 iso文件挂载到本地目录. 1.挂载光驱: 将cdrom 放入光驱. $  mkdir /media/cdr ...

  3. 微信小程序初识

    http://lib.csdn.net/article/wechat/46742 微信小程序的前途和定位有什么疑惑?点进去 简单先记几个印象名词:流量入口,线下是重点,“即用即走”适合低频工具类产品. ...

  4. 如何通过以太坊智能合约来进行众筹(ICO)

    前面我们有两遍文章写了如何发行代币,今天我们讲一下如何使用代币来公开募资,即编写一个募资合约. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还 ...

  5. PHP 是一门弱类型语言

    PHP 是一门弱类型语言 我们注意到,不必向 PHP 声明该变量的数据类型. PHP 会根据变量的值,自动把变量转换为正确的数据类型. 在强类型的编程语言中,我们必须在使用变量前先声明(定义)变量的类 ...

  6. 如何使用 libqr 库生成二维码?

    使用 libqr 库只需 4 步即可生成二维码 1.初始化 QRCode 结构体 QRCode *qrInit(int version, int mode, int eclevel, int mask ...

  7. hdu1006 Tick and Tick

    原题链接 Tick and Tick 题意 计算时针.分针.秒针24小时之内三个指针之间相差大于等于n度一天内所占百分比. 思路 每隔12小时时针.分针.秒针全部指向0,那么只需要计算12小时内的百分 ...

  8. POJ - 1062 昂贵的聘礼 Dijkstra

    思路:构造最短路模型,抽象出来一个源点,这个源点到第i个点的费用就是price[i],然后就能抽象出图来,终点是1. 任意两个人之间都有等级限制,就枚举所有最低等级限制,然后将不再区间[min_lev ...

  9. MongoDB,分组,聚合

    使用聚合,db.集合名.aggregate- 而不是find 管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数.MongoDB的聚合管道将MongoDB文档在一个管道处理完 ...

  10. Nginx + uwsgi + django + websocket(dwebsocket)环境部署

    1.安装nginx(/export/servers/nginx/) 保证/export/servers/nginx/是nginx的安装目录 /export/servers/nginx/conf/dom ...