bzoj 1150&2151&2288(双向链表+堆)(贪心)
经典模型:在n个点中选k个点,要求两两不相邻,且总权值最大/最小。
做法:用双向链表串起来,把所有点丢进堆里,选择一个点的时候把它左右两个点从双向链表和堆中去除,然后把这个点的权值加进ans,出堆后改为左右两边的权值-当前权值重新入堆,重复k次,ans即为答案
原理:左右两边的权值-当前权值相当于这个点不选,改为选左右两边的点,并且多选了一个点,重复k次后必然取到k个点
三道同类型题
bzoj1150:显然一段网线肯定接在相邻的两个点,于是把相邻的点的距离求出来,问题就变成经典模型了
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
const int maxn=,inf=1e9;
struct poi{int pos,dis;};
priority_queue<poi>q;
bool operator<(poi a,poi b){return a.dis>b.dis;}
int n,k,a[maxn],dis[maxn],pre[maxn],next[maxn];
ll ans;
bool v[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
inline void del(int x)
{
int l=pre[x],r=next[x];
pre[x]=next[x]=;
next[l]=r;pre[r]=l;
}
int main()
{
read(n);read(k);
for(int i=;i<=n;i++)read(a[i]);
for(int i=;i<n;i++)dis[i]=a[i+]-a[i],q.push((poi){i,dis[i]});dis[]=dis[n]=inf;
for(int i=;i<n;i++)pre[i]=i-,next[i]=i+;
for(int i=;i<=k;i++)
{
poi t=q.top();
while(v[t.pos])q.pop(),t=q.top();
ans+=t.dis;v[pre[t.pos]]=v[next[t.pos]]=;
dis[t.pos]=dis[pre[t.pos]]+dis[next[t.pos]]-dis[t.pos];
q.pop();q.push((poi){t.pos,dis[t.pos]});
del(pre[t.pos]);del(next[t.pos]);
}
printf("%lld\n",ans);
return ;
}
bzoj2151:双向链表首尾串起来,问题就变成经典模型了
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
const int maxn=,inf=1e9;
struct poi{int pos,dis;};
priority_queue<poi>q;
bool operator<(poi a,poi b){return a.dis<b.dis;}
int n,k,a[maxn],dis[maxn],pre[maxn],next[maxn];
ll ans;
bool v[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
inline void del(int x)
{
int l=pre[x],r=next[x];
pre[x]=next[x]=;
next[l]=r;pre[r]=l;
}
int main()
{
read(n);read(k);
if(k>n>>)return puts("Error!"),;
for(int i=;i<=n;i++)read(dis[i]),q.push((poi){i,dis[i]});
for(int i=;i<=n;i++)pre[i]=i-,next[i]=i+;pre[]=n;next[n]=;
for(int i=;i<=k;i++)
{
poi t=q.top();
while(v[t.pos])q.pop(),t=q.top();
ans+=t.dis;v[pre[t.pos]]=v[next[t.pos]]=;
dis[t.pos]=dis[pre[t.pos]]+dis[next[t.pos]]-dis[t.pos];
q.pop();q.push((poi){t.pos,dis[t.pos]});
del(pre[t.pos]);del(next[t.pos]);
}
printf("%lld\n",ans);
return ;
}
bzoj2288:
这题比较复杂。首先可以发现正数连续的一段和负数连续的一段要取肯定是都得同时取的,那么就可以把连续的同正负的数缩成一个了。然后如果正数个数不大于k,直接取所有正数即可。如果正数个数大于k,我们考虑舍弃一些正数,或者选择一些负数。只要将所有数取绝对值,问题就变成经典模型了。为什么呢?
我们选择的是总权值最小的数,如果他是个正数,相当于舍弃,如果是负数,相当于把左右两端的正数连成一段。显然不可能同时选两个相邻的数,否则一定是正负一起选,那负数完全可以不选,因为既然你要丢弃这个正数,为何还要选择一个负数呢,选择负数的作用只有连接左右两端的正数。
因此,这个题也能转化为经典模型,就可以写了。
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
const int maxn=,inf=1e9;
struct poi{int pos,dis;};
priority_queue<poi>q;
bool operator<(poi a,poi b){return a.dis>b.dis;}
int n,m,flag,N,now,l,r,ans;
int a[maxn],s[maxn],pre[maxn],next[maxn];
bool v[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
inline void del(int x)
{
int l=pre[x],r=next[x];
pre[x]=next[x]=;
pre[r]=l;next[l]=r;
}
int main()
{
read(n);read(m);
for(int i=;i<=n;i++)read(a[i]);
int l=,r=n;
while(a[l]<=&&l<=n)l++;
while(a[r]<=&&r)r--;
for(int i=l;i<=r;)
{
if(a[i]>=)flag=;else flag=-;
for(now=;flag*a[i]>=&&i<=r;i++)now+=a[i];
s[++N]=now;
}
for(int i=;i<=N;i+=)ans+=s[i];
if(m>=(N+)>>)return printf("%d\n",ans),;
for(int i=;i<=N;i++)q.push((poi){i,s[i]=(s[i]>?s[i]:-s[i])});
for(int i=;i<=N;i++)pre[i]=i-,next[i]=i+;s[]=inf;s[N+]=inf;
int up=((N+)>>)-m;
for(int i=;i<=up;i++)
{
poi t=q.top();
while(v[t.pos])q.pop(),t=q.top();q.pop();
s[t.pos]=s[pre[t.pos]]+s[next[t.pos]]-s[t.pos];
ans-=t.dis;q.push((poi){t.pos,s[t.pos]});
v[pre[t.pos]]=v[next[t.pos]]=;
del(pre[t.pos]);del(next[t.pos]);
}
printf("%d\n",ans);
return ;
}
bzoj 1150&2151&2288(双向链表+堆)(贪心)的更多相关文章
- BZOJ 1029: [JSOI2007]建筑抢修 堆+贪心
1029: [JSOI2007]建筑抢修 Description 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有 ...
- BZOJ 1150--数据备份(链表&堆&贪心)
1150: [CTSC2007]数据备份Backup Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2572 Solved: 1038[Submit ...
- [BZOJ 1150] [CTSC2007] 数据备份Backup 【贪心 + 链表】
题目链接:BZOJ - 1150 题目分析 可以看出,我们选的 k 条边一定是相邻两点之间的线段.我们可以将每条边看成一个点,那么我们就是要在 n-1 个点中选出互不相邻的 k 个,使它们的和最小. ...
- [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆)
[BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆) 题面 给出一个长度为n的序列,选k段长度在L到R之间的区间,一个区间的值等于区间内所有元素之的和,使得k个区间的值之和最大.区 ...
- 洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心)
洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/132 ...
- BZOJ_2802_[Poi2012]Warehouse Store_堆+贪心
BZOJ_2802_[Poi2012]Warehouse Store_堆+贪心 Description 有一家专卖一种商品的店,考虑连续的n天. 第i天上午会进货Ai件商品,中午的时候会有顾客需要购买 ...
- BZOJ_1150_[CTSC2007]数据备份Backup_堆+贪心
BZOJ_1150_[CTSC2007]数据备份Backup_堆+贪心 Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏 ...
- P4053 [JSOI2007]建筑抢修 堆贪心
思路:堆贪心 提交:1次 题解: 先按时间\(sort\),然后如果能修就直接扔堆里,不能修取堆顶比一下时间长短,把时间短的扔进堆: #include<cstdio> #include&l ...
- HDU5124lines题解-堆+贪心的一个新方法
题目链接 https://cn.vjudge.net/problem/HDU-5124 胡扯 感觉说新方法好像有点不太好,但是翻了十几篇博客都是清一色离散化之类的... 为什么会做这道题呢?因为前几天 ...
随机推荐
- 第六阶段·数据库MySQL及NoSQL实践 第2章·Redis
01-Redis简介 02-Redis基本安装启动 03-Redis的配置文件基本使用 04-Redis安全管理 05-Redis安全持久化-RDB持久化 06-Redis安全持久化-AOF持久化 0 ...
- Java开发工程师(Web方向) - 03.数据库开发 - 第2章.数据库连接池
第2章--数据库连接池 数据库连接池 一般而言,在实际开发中,往往不是直接使用JDBC访问后端数据库,而是使用数据库连接池的机制去管理数据库连接,来实现对后端数据库的访问. 建立Java应用程序到后端 ...
- 【WXS数据类型】Object
Object 是一种无序的键值对. 属性: 名称 值类型 说明 [Object].constructor [String] 返回值为“Object”,表示类型的结构字符串 方法: 原型:[Object ...
- django启动创建用户失败
a django应用启动 b 访问127.0.0.1:8000,报错信息如下,原因为没有这个用户需要创建下用户 c 创建用户过程中报错原因是因为添加了app需要告诉django,这个 模型发生了改变, ...
- Ubuntu 常用软件推荐(QQ、微信、MATLAB等)及安装过程
1. Wine QQ QQ 移植到 Linux 一直是一个比较头疼的问题,但我们日常交流.传输文件又离不开这个软件.在网上一番搜寻尝试后,发现最好的替代方案就是 Wine QQ,版本也还比较新,缺点是 ...
- 软工第三次作业——个人PSP
9.22--9.26本周例行报告 1.PSP(personal software process )个人软件过程. 类型 任务 预计时间 开始时间 结束时间 中断时间 实际用时 准备工作 学习重定向 ...
- Java package和import语句
Java中的package和import语句 如果你想让其他人访问你的类,你一定要把你写的类放到正确的子目录下. 在Java里,对于位于包中的类是这样管理的: Java编译器把包对应于文件系统的目录管 ...
- UVALive - 6864 Strange Antennas 扫描线
题目链接: http://acm.hust.edu.cn/vjudge/problem/87213 Strange Antennas Time Limit: 3000MS 题意 一个雷达能够辐射到的范 ...
- 什么是Processing
Processing是一种计算机语言,以JAVA语法为基础,可转化成JAVA程序,不过在语法上简易许多.所有的原始代码及开发环境开放,主要用于艺术.影像.影音的设计与处理. 其次为什么要介绍这款软件呢 ...
- hexo设置permalink-避免url中出现中文
hexo博客初始化的url是年月日+题目:year/:month/:day/:title/,这样的url不便与分享,中文会乱吗,而且一旦修改了题目(我相信大部分人的题目都是中文)就会导致之前分享的ur ...