若想要深入学习反悔贪心,传送门


Description:

有 \(n\) 个位置,每个位置有一个价值。有 \(m\) 个树苗,将这些树苗种在这些位置上,相邻位置不能都种。求可以得到的最大值或无解信息。

Method

先判断无解的情况,我们显然可以发现,若 \(n<\frac{2}{m}\) ,则是不能在合法的条件下种上 \(m\) 棵树的,故按题意输出Error!即可。

假如有解的话,我们可以很轻松的推出贪心策略:在合法的情况下选择最大的价值。

显然上面的策略是错误的,我们选择了最大价值的点,相邻的两个点就不能选,而选择相邻两个点得到的价值可能更大。

考虑如何设计反悔策略。

我们同样用差值来达到反悔的目的。假设有 \(A\) ,\(B\) ,\(C\) ,\(D\) 四个相邻的点(如图)。

\(A\) 点的价值为 \(a\) ,其他点同理。若:

\[a+c>b+d
\]

则:

\[a+c-b>d
\]

假如我们先选了 \(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 题解的更多相关文章

  1. Guard Duty (medium) Codeforces - 958E2 || (bzoj 2151||洛谷P1792) 种树 || 编译优化

    https://codeforces.com/contest/958/problem/E2 首先求出N个时刻的N-1个间隔长度,问题就相当于在这些间隔中选K个数,相邻两个不能同时选,要求和最小 方法1 ...

  2. [洛谷P3376题解]网络流(最大流)的实现算法讲解与代码

    [洛谷P3376题解]网络流(最大流)的实现算法讲解与代码 更坏的阅读体验 定义 对于给定的一个网络,有向图中每个的边权表示可以通过的最大流量.假设出发点S水流无限大,求水流到终点T后的最大流量. 起 ...

  3. 洛谷P5759题解

    本文摘自本人洛谷博客,原文章地址:https://www.luogu.com.cn/blog/cjtb666anran/solution-p5759 \[这道题重在理解题意 \] 选手编号依次为: \ ...

  4. 关于三目运算符与if语句的效率与洛谷P2704题解

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...

  5. c++并查集配合STL MAP的实现(洛谷P2814题解)

    不会并查集的话请将此文与我以前写的并查集一同食用. 原题来自洛谷 原题 文字稿在此: 题目背景 现代的人对于本家族血统越来越感兴趣. 题目描述 给出充足的父子关系,请你编写程序找到某个人的最早的祖先. ...

  6. 洛谷P2607题解

    想要深入学习树形DP,请点击我的博客. 本题的DP模型同 P1352 没有上司的舞会.本题的难点在于如何把基环树DP转化为普通的树上DP. 考虑断边和换根.先找到其中的一个环,在上面随意取两个点, 断 ...

  7. 【洛谷】题解 P1056 【排座椅】

    题目链接 因为题目说输入保证会交头接耳的同学前后相邻或者左右相邻,所以一对同学要分开有且只有一条唯一的通道才能把他们分开. 于是可以吧这条通道累加到一个数组里面.应为题目要求纵列的通道和横列的通道条数 ...

  8. [洛谷P1792][国家集训队]种树

    题目大意:给出由$n$个数组成的环,取某个数就可以得到它的分数,相邻的两个数不能同时取.问取$m$个数可以得到的最大分数. 题解:建一个大根堆,贪心取,每个点记录前驱后继,取一个点就把前驱后继设成不能 ...

  9. 洛谷P3572题解

    这道题实在是一道 毒瘤 题,太坑爹了.那个写 \(deque\) 的题解亲测只有80分,原因 不言而明 ,这道题居然 丧心病狂 到 卡STL . 好了,不吐槽了,进入正题 题目分析: 这是一道十分 简 ...

随机推荐

  1. latex制作表格-跨行跨列

    1.列的合并,使用 \multicolumn{跨几列}{格式}{填充内容} \documentclass[UTF8]{ctexart} \begin{document} 三囚犯问题进行300次实验后\ ...

  2. C# 练习题 利用条件运算符的嵌套来完成分数等级划分

    题目:利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示.1.程序分析:(a>b)?a:b这是条件运算符的基本例子. cla ...

  3. Excel导出,添加有效性

    #region  添加有效性 DataTable dt = LAbll.LogisticsAccounts(DeptId); //查数据 if (dt.Rows.Count < 20) //有效 ...

  4. Java自学-接口与继承 内部类

    Java 内部类 内部类分为四种: 非静态内部类 静态内部类 匿名类 本地类 步骤 1 : 非静态内部类 非静态内部类 BattleScore "战斗成绩" 非静态内部类可以直接在 ...

  5. nodejs npm vue yarn 环境搭建

    1.nodejs中文网http://nodejs.cn/download/下载最新版本 2.安装注意,虽然.msi包没有右键用管理员权限运行,如果直接双击安装可能会存在安装失败的问题.使用管理员权限运 ...

  6. HTML5深入学习之 WebSQL 数据库

    概述 WebSQL 并不是 HTML5规范的一部分,而是一个独立的规范,它可以用来做一些离线应用 核心API openDatabase() => 用来打开或创建数据库(没有时则创建,有则打开) ...

  7. 87.CSS Flex 弹性盒模型布局教程(共用的css在48篇文章gird)

    CSS Flex 弹性盒模型布局教程 Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性. flex布局就是给任何一个容器添加 dis ...

  8. ES6的新特性

    ECMAScript 6(简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,又称ECMAScript 2015.ES6就是ES2015. 虽然目前并不是所有 ...

  9. Cheat Engine 特征码

    打开游戏 引用自动注入 搜索特征码 特征码,是游戏运行中,唯一的汇编代码 验证,特征码是游戏中唯一代码 添加特征码 添加特征码,以及金钱只增不减代码 进行激活测试 特征码,只有在游戏过程中才会执行到 ...

  10. mysql 查询当天数据

    查询当天数据 select * from tab where FROM_UNIXTIME(fabutime, '%Y%m%d') = 20121217;   mysql TO_DAYS(date) 函 ...