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


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. [個人紀錄] git 設定

    -- git history git config --global alias.history=log --graph --all --pretty=format:'%C(bold blue)%H% ...

  2. WebAPI 身份认证解决方案——Phenix.NET企业应用软件快速开发平台.使用指南.21.WebAPI服务(一)

    21   WebAPI服务 ASP.NET Web API,是微软在.NET Framework 4.5上推出的轻量级网络服务框架,虽然作为ASP.NET MVC 4的一部分,但却是一套全新的.独立的 ...

  3. 笔记:Java Language Specification - 章节17- 线程和锁

    回答一个问题:多线程场景下,有时一个线程对shared variable的修改可能对另一个线程不可见.那么,何时一个线程对内存的修改才会对另一个线程可见呢? 基本的原则: 如果 读线程 和 写线程 不 ...

  4. 第一阶段:Java基础 1.JAVA开发介绍---2. JVM、JRE、JDK之间的关系

    JDK :英文名称(Java Development Kit),Java 开发工具包,是针对 Java 开发员的产品.jdk 是整个 Java 开发的核心,包括了Java运行环境JRE.Java工具和 ...

  5. SpringMVC+EasyUI实现页面左侧导航菜单

    1. 效果图展示 2. 工程目录结构 注意: webapp下的resources目录放置easyui和js(jQuery文件是另外的)                    3. 代码 index.j ...

  6. 使用 sql server 默认跟踪分析执行的 SQL 语句

    如果没有启用 SQL SERVER 的跟踪器来跟踪 SQL SERVER 的 SQL 执行情况,又想查最近的 SQL 执行情况,网上一般说是使用 LogExprorer 这个工具,网上找了这个工具很久 ...

  7. Could not get lock /var/lib/dpkg/lock-frontend解决

    在安装软件包时如果出现Could not get lock /var/lib/dpkg/lock-frontend,说明之前使用apt时出现异常,没有正常关闭,还在运行. lgj@lgj-Lenovo ...

  8. Python基础(四)--数据类型、字符编码、文件处理

    一.数据类型 1. 数据类型 数字(整形,长整形,浮点型,复数) 字符串 字节串(字节bytes类型) 列表 元组 字典 集合 2. 按照以下几个点展开数据类型的学习 #=============== ...

  9. golang之类型零值初始化及比较

    综述 变量声明时未赋初值,则变量被自动赋值为该类型的零值(固定值) func new(Type) *Type new()返回一个指针,指向新分配的该类型的零值,不是空指针(nil).the value ...

  10. 用 ConfigMap 管理配置

    1. ConfigMap介绍管理配置 ConfigMap介绍 Secret 可以为 Pod 提供密码.Token.私钥等敏感数据:对于一些非敏感数据,比如应用的配置信息,则可以用 ConfigMap ...