经典模型:在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(双向链表+堆)(贪心)的更多相关文章

  1. BZOJ 1029: [JSOI2007]建筑抢修 堆+贪心

    1029: [JSOI2007]建筑抢修 Description 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有 ...

  2. BZOJ 1150--数据备份(链表&堆&贪心)

    1150: [CTSC2007]数据备份Backup Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2572  Solved: 1038[Submit ...

  3. [BZOJ 1150] [CTSC2007] 数据备份Backup 【贪心 + 链表】

    题目链接:BZOJ - 1150 题目分析 可以看出,我们选的 k 条边一定是相邻两点之间的线段.我们可以将每条边看成一个点,那么我们就是要在 n-1 个点中选出互不相邻的 k 个,使它们的和最小. ...

  4. [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆)

    [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆) 题面 给出一个长度为n的序列,选k段长度在L到R之间的区间,一个区间的值等于区间内所有元素之的和,使得k个区间的值之和最大.区 ...

  5. 洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心)

    洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/132 ...

  6. BZOJ_2802_[Poi2012]Warehouse Store_堆+贪心

    BZOJ_2802_[Poi2012]Warehouse Store_堆+贪心 Description 有一家专卖一种商品的店,考虑连续的n天. 第i天上午会进货Ai件商品,中午的时候会有顾客需要购买 ...

  7. BZOJ_1150_[CTSC2007]数据备份Backup_堆+贪心

    BZOJ_1150_[CTSC2007]数据备份Backup_堆+贪心 Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏 ...

  8. P4053 [JSOI2007]建筑抢修 堆贪心

    思路:堆贪心 提交:1次 题解: 先按时间\(sort\),然后如果能修就直接扔堆里,不能修取堆顶比一下时间长短,把时间短的扔进堆: #include<cstdio> #include&l ...

  9. HDU5124lines题解-堆+贪心的一个新方法

    题目链接 https://cn.vjudge.net/problem/HDU-5124 胡扯 感觉说新方法好像有点不太好,但是翻了十几篇博客都是清一色离散化之类的... 为什么会做这道题呢?因为前几天 ...

随机推荐

  1. PLSQL-包函数存储过程

    包: 包是PLSQL中多个单元的逻辑组合,他将过程组合在一个包内容,以供用户调用,使用后,不需要程序员频繁的修改程序,可以保持程序的逻辑完整性,对包中的过程重新定义或者编译,以便修改部分功能,从而更好 ...

  2. 说一说VIN码识别,车架号识别那些事

    对于有车一族的朋友来说,日常接触比较多的是车牌.行驶证.驾驶证,而知道VIN码/车架号码的比较少. 其实,对于车辆来说,VIN码/车架号码非常重要,它就像人的身份证一样,VIN码/车架号码是车辆唯一的 ...

  3. web漏洞原理 (需要每周更新此篇文章)

    SQL注入攻击简介 结构化查询语言SQL是用来和关系数据库进行交互的文本语言.它允许用户对数据进行有效的管理,包含了对数据的查询.操作.定义和控制等几个方面,例如向数据库写入.插入数据,从数据库读取数 ...

  4. 使用InstallShield-Limited-Edition制作安装包

    1.打开此网站,进行注册,获取序列码以及下载InstallShield-Limited-Edition 2.安装完成之后,打开VisualStudio,新建项目 3.填写基本应用信息 4.配置相关信息 ...

  5. unity实现框选效果

    思路: 在uinity中既可以将屏幕坐标转换为世界坐标,也可以将世界坐标转换为屏幕坐标.这样的话我们就可以通过判断物体在世界坐标转换为平幕坐标是否在鼠标框选的矩形区域坐标内,来判断物体是否在框选范围. ...

  6. [JSON].remove( keyPath )

    语法:[JSON].remove( keyPath ) 返回:无 说明:移除指定路径的键 示例: Set jsonObj = toJson("{div:{'#text-1': 'is tex ...

  7. Juice账号

    zhangxiaocong69 zxc6545398 15657167502 区块链账户: 0x00680404766965143796a0a070835c3cdf9a4a50

  8. python函数中的位置参数、默认参数、关键字参数、可变参数区别

    一.位置参数 调用函数时根据函数定义的参数位置来传递参数. #!/usr/bin/env python # coding=utf-8 def print_hello(name, sex): sex_d ...

  9. POJ 1696 Space Ant(凸包变形)

    Description The most exciting space discovery occurred at the end of the 20th century. In 1999, scie ...

  10. Thunder团队第三周 - Scrum会议7

    Scrum会议7 小组名称:Thunder 项目名称:i阅app Scrum Master:胡佑蓉 工作照片: 邹双黛在照相,所以图片中没有该同学. 参会成员: 王航:http://www.cnblo ...