经典模型:在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. java后台接收微信服务号/订阅号消息

    1.申请订阅号(适合个人)或者服务号(适合企业) 微信公众平台 2.填写配置 服务器地址: 需要接收消息 的服务端接口地址 令牌:通话识别码,随便写,后端接收时,使用一样的就可以了. 消息加密秘钥 : ...

  2. leetcode-全排列详解(回溯算法)

     全排列     给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2 ...

  3. 本地矩阵(Local Matrix)

    本地矩阵具有整型的行.列索引值和双精度浮点型的元素值,它存储在单机上.MLlib支持稠密矩阵DenseMatrix和稀疏矩阵Sparse Matrix两种本地矩阵,稠密矩阵将所有元素的值存储在一个列优 ...

  4. Python实现个性化推荐一

    现如今,网站用推荐系统为你提供个性化的体验,告诉你买啥,吃啥甚至你应该和谁交朋友.尽管每个人口味不同,但大体都适用这个套路.人们倾向于喜欢那些与自己喜欢的其他东西相似的东西,也倾向于与自己身边的人有相 ...

  5. canvas学习(一):线条,图像变换和状态保存

    canvas学习(一):线条,图像变换和状态保存 一:绘制一条线段: var canvas = document.getElementById('canvas') var ctx = canvas.g ...

  6. 计算器软件实现系列(七)WPF+SQL+策略模式

    一  整体概述 本次设计主要是在WPF的页面中实现的,属于表现层的更换,数据库部分用的还是数据库的封装,其中引用了策略模式 二  设计思路 1 在出题页面,进行试题的编辑,在编辑后会自动保存到数据库中 ...

  7. DAY3敏捷冲刺

    站立式会议 工作安排 (1)服务器配置 (2)数据库配置 燃尽图 燃尽图有误,已重新修改,先贴卡片的界面,后面补修改后燃尽图 代码提交记录

  8. eg_1

    1. 编写一个程序,输出一个字符串中的大写英文字母个数,小写英文字母个数以及非英文字母个数. 第一种方法: public class Test { public static void main(St ...

  9. ZOJ 1666 G-Square Coins

    https://vjudge.net/contest/67836#problem/G People in Silverland use square coins. Not only they have ...

  10. c#控件的name和text属性有什么不同?

    text 是显示出来,供用户和自己编辑方便使用的,name 属性是编辑代码用的. 比如要读取一个text栏的内容 取name='txtName' text='姓名'代码段需要写的是, txtName. ...