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 . 好了,不吐槽了,进入正题 题目分析: 这是一道十分 简 ...
随机推荐
- 使用VBA将Excel指定单元格数据、字符串或者图表对象插入到Word模板指定书签处
准备工作: 1.首先需要提供一个word模板,并且标记好您要插入书签的位置,定义书签的命名.如图 2.模拟您要插入的Excel原始数据和图表对象 插入代码如下: Private Sub Command ...
- 22、vue实现随机四位数验证码
效果图: 1.新建生成验证码的组件Sidentify.vue(代码如下): <template> <div class="s-canvas"> <ca ...
- FreeRTOS 任务通知模拟计数型信号量
举例 //释放计数型信号量任务函数 void SemapGive_task(void *pvParameters) { u8 key; while(1) { key = KEY_Scan(0); // ...
- idea 端口被占用
打开你的DOS命令首先输入 netstat -ano|findstr 8088 (8088即为被占用的端口号) 再输入taskkill /pid 7348 /f (7348即为上 ...
- Detectron2源码阅读笔记-(一)Config&Trainer
代码结构概览 核心部分 configs:储存各种网络的yaml配置文件 datasets:存放数据集的地方 detectron2:运行代码的核心组件 tools:提供了运行代码的入口以及一切可视化的代 ...
- Tensorflow中保存模型时生成的各种文件区别和作用
假如我们得到了如下的checkpoints, 上面的文件主要可以分成三类:一种是在保存模型时生成的文件,一种是我们在使用tensorboard时生成的文件,还有一种就是plugins这个文件夹,这个是 ...
- SpringDataJPA开发环境的搭建
这里简单的介绍一下使用maven工程创建SpringDataJPA的开发环境的搭建 首先引入依赖 <dependencies> <!-- junit单元测试 --> <d ...
- django小知识(2)
昨日内容回顾 1.choices参数 class Userinfo(models.Model): username = ... age = ... gender_choice = ( (1,'male ...
- beta冲刺总结那周余嘉熊掌将得队
作业格式 课程名称:软件工程1916|W(福州大学) 作业要求:项目Beta冲刺 团队名称: 那周余嘉熊掌将得队 作业目标:beta冲刺总结 队员学号 队员姓名 博客地址 备注 221600131 J ...
- JUnit 5.x 知识点
出处:https://blinkfox.github.io/2018/11/15/hou-duan/java/dan-yuan-ce-shi-zhi-nan/#toc-heading-14 表面上来看 ...