BZOJ2151/洛谷P1792 题解
若想要深入学习反悔贪心,传送门。
Description:
有 \(n\) 个位置,每个位置有一个价值。有 \(m\) 个树苗,将这些树苗种在这些位置上,相邻位置不能都种。求可以得到的最大值或无解信息。
Method:
先判断无解的情况,我们显然可以发现,若 \(n<\frac{2}{m}\) ,则是不能在合法的条件下种上 \(m\) 棵树的,故按题意输出Error!即可。
假如有解的话,我们可以很轻松的推出贪心策略:在合法的情况下选择最大的价值。
显然上面的策略是错误的,我们选择了最大价值的点,相邻的两个点就不能选,而选择相邻两个点得到的价值可能更大。
考虑如何设计反悔策略。
我们同样用差值来达到反悔的目的。假设有 \(A\) ,\(B\) ,\(C\) ,\(D\) 四个相邻的点(如图)。
\(A\) 点的价值为 \(a\) ,其他点同理。若:
\]
则:
\]
假如我们先选了 \(B\) 点,我们就不能选 \(A\) 和 \(C\) 两点,这显然是不对的,但我们可以新建一个节点 \(P\) , \(P\) 点的价值为 \(a+c-b\) ,再删去 \(B\) 点。(如图,红色的是删去的点,橙色的新建的点)
下一次选择的点是 \(P\) 的话,说明我们反悔了(即相当于 \(B\) 点没有选),可以保证最后的贪心最优解是全局最优解。
如何快速插入 \(P\) 点和找出是否选择 \(P\) 点呢?我们可以使用双向链表和小根堆,使得最终在 \(O(n\log n)\) 的时间复杂度下快速求出全局最优解。
Code:
#include<bits/stdc++.h>
#define int long long
#define Maxn 2000010
using namespace std;
inline void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,m;
int w[Maxn],lft[Maxn],rgh[Maxn];
struct node
{
int val,id;
bool operator <(const node &n) const
{
return val<n.val;
}
};
priority_queue<node>qu;
int ind,ans=0;
int vis[Maxn];
signed main()
{
read(n),read(m);
ind=n;
if(n/2<m)
{
puts("Error!");
return 0;
}
for(int i=1;i<=n;i++)
{
read(w[i]);
node tmp;
tmp.id=i;
tmp.val=w[i];
qu.push(tmp);
if(i==1)
{
lft[i]=n;
rgh[i]=i+1;
}else if(i==n)
{
lft[i]=i-1;
rgh[i]=1;
}else
{
lft[i]=i-1;
rgh[i]=i+1;
}
}
for(int i=1;i<=m;i++)
{
while(vis[qu.top().id]) qu.pop();
int id=qu.top().id;
int val=qu.top().val;
qu.pop();
ans+=val;
ind++;
vis[lft[id]]=vis[rgh[id]]=1;
lft[rgh[rgh[id]]]=ind;rgh[lft[lft[id]]]=ind;
lft[ind]=lft[lft[id]];rgh[ind]=rgh[rgh[id]];
w[ind]=w[lft[id]]+w[rgh[id]]-val;
int newid=ind;
int newval=w[ind];
node tmp;
tmp.id=newid;
tmp.val=newval;
qu.push(tmp);
}
printf("%lld\n",ans);
return 0;
}
Warning:
一定要记录这个点选没有选过,假如已经选过了,就从堆中丢出去;
1与 \(n\) 是相邻的,一定要特判一下;
双向链表一定不要写挂了;
一定要先将新建的点的价值存入一开始的价值数组,再丢进堆里;(卡在45卡了好久)
index是关键字,一定不要使用。(我成功CE了一次)
BZOJ2151/洛谷P1792 题解的更多相关文章
- Guard Duty (medium) Codeforces - 958E2 || (bzoj 2151||洛谷P1792) 种树 || 编译优化
https://codeforces.com/contest/958/problem/E2 首先求出N个时刻的N-1个间隔长度,问题就相当于在这些间隔中选K个数,相邻两个不能同时选,要求和最小 方法1 ...
- [洛谷P3376题解]网络流(最大流)的实现算法讲解与代码
[洛谷P3376题解]网络流(最大流)的实现算法讲解与代码 更坏的阅读体验 定义 对于给定的一个网络,有向图中每个的边权表示可以通过的最大流量.假设出发点S水流无限大,求水流到终点T后的最大流量. 起 ...
- 洛谷P5759题解
本文摘自本人洛谷博客,原文章地址:https://www.luogu.com.cn/blog/cjtb666anran/solution-p5759 \[这道题重在理解题意 \] 选手编号依次为: \ ...
- 关于三目运算符与if语句的效率与洛谷P2704题解
题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...
- c++并查集配合STL MAP的实现(洛谷P2814题解)
不会并查集的话请将此文与我以前写的并查集一同食用. 原题来自洛谷 原题 文字稿在此: 题目背景 现代的人对于本家族血统越来越感兴趣. 题目描述 给出充足的父子关系,请你编写程序找到某个人的最早的祖先. ...
- 洛谷P2607题解
想要深入学习树形DP,请点击我的博客. 本题的DP模型同 P1352 没有上司的舞会.本题的难点在于如何把基环树DP转化为普通的树上DP. 考虑断边和换根.先找到其中的一个环,在上面随意取两个点, 断 ...
- 【洛谷】题解 P1056 【排座椅】
题目链接 因为题目说输入保证会交头接耳的同学前后相邻或者左右相邻,所以一对同学要分开有且只有一条唯一的通道才能把他们分开. 于是可以吧这条通道累加到一个数组里面.应为题目要求纵列的通道和横列的通道条数 ...
- [洛谷P1792][国家集训队]种树
题目大意:给出由$n$个数组成的环,取某个数就可以得到它的分数,相邻的两个数不能同时取.问取$m$个数可以得到的最大分数. 题解:建一个大根堆,贪心取,每个点记录前驱后继,取一个点就把前驱后继设成不能 ...
- 洛谷P3572题解
这道题实在是一道 毒瘤 题,太坑爹了.那个写 \(deque\) 的题解亲测只有80分,原因 不言而明 ,这道题居然 丧心病狂 到 卡STL . 好了,不吐槽了,进入正题 题目分析: 这是一道十分 简 ...
随机推荐
- HDFS文件浏览页返回上级目录功能
1.效果预览 Hadoop自带的效果 修改后,多了一个../按钮,点击可以回到上级目录 2.查找页面和JS文件 我们在浏览器上可以看到访问了explorer.html页面,可以尝试使用find命令查找 ...
- Mycat分布式数据库架构解决方案--Mycat实现数据库分表
echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 准备工 ...
- Vue安装及项目介绍
目录 创建Vue项目 环境安装 创建项目 pycharm打开Vue项目 项目目录介绍 入口文件(main.js) 路由配置(router.js ) 组件 前台路由的基本工作流程 目录结构 根组件(Ap ...
- Javaweb项目-下拉列表显示后台数据库的数据
下面将演示前端下拉列表显示后台数据库中class表的说有班级的名称 环境: Tomcat-8.5.40 mysql-8.0.13 eclipse-4.9.0 springmvc框架 一.从mysql中 ...
- HTML 注释 和 实体字符
一.注释 在HTML中还有一种特殊的标签——注释标签.如果需要在HTML文档中添加一些便于阅读和理解但又不需要显示在页面中的注释文字,就需要使用注释标签. 注释内容不会显示在浏览器窗口中,但是作为HT ...
- 金融finaunce财经
金融 (经济学术语) 金融是货币资金融通的总称.主要指与货币流通和银行信用相关的各种活动.主要内容包括: 货币的发行.投放.流通和回笼:各种存款的吸收和提取:各项贷款的发放和收回:银行会计.出纳.转账 ...
- android 连接wifi案例
1.xml布局文件: <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmln ...
- 安卓样式Style和主题Theme
1. 区别 不过style是针对view来说的,比如TextView和EditText这些:而Theme必须针对整个activity或者整个application 2. 样式 创建一个样式,根元素 & ...
- elasticsearch must 和 should 并列的情况
在elasticsearch中如果要对几个字段进行查询,然后其中有一个字段可以有多个取值的时候,正常想到的要用should,其实就是或的关系.但是正确的做法,应该是把should并列的条件整合到一个b ...
- RabbitMQ基本概念(四)-服务详细配置与日常监控管理
RabbitMQ服务管理 启动服务:rabbitmq-server -detached[ /usr/local/rabbitmq/sbin/rabbitmq-server -detached ] 查看 ...