\(\\\)

\(Description\)


给出一个数轴上\(N\)个点的坐标\(A_i\),选择\(K\)个点对,使得这\(K\)个点对每个点对的距离之和尽可能小。

  • \(N\in [0,10^5]\),\(K\in [0,\frac{N}{2}]\),\(A_i\in [0,10^9]\)

\(\\\)

\(Solution\)


  • 排序,求出相邻两两间距\(D_i\),问题转化为选\(K\)个互不相邻的间距
  • 将所有的间距放到一个小根堆中,每次取堆顶加入答案。如果选择了\(D_i\),则在堆中删去\(D_i,D_{i-1},D_{i+1}\),并将\(D_{i-1}+D_{i+1}-D_i\)加入堆中,去执行选\(K-1\)个值得子问题。
  • 这样做法的合理性在于,如果每次选则的是原来的\(D_i\),那么就是直接加入这个答案,如果选择的是某次操作后的\(D_{i-1}+D_{i+1}-D_i\),那么代表\(D_i\)在此前一定加入过答案,此时答案里累加上这个数代表,从答案中去掉原来选择的\(D_i\),加入\(D_i\)两侧的数,同样会使得选则的间距\(+1\)。
  • 注意,在合并边界元素时,如果再次进行反转操作并不会使选中的段数增加,所以如果边界被合并了一次重置该位置数字时应设为正无穷。
  • 可以发现几次操作以后前驱后继就很难寻找了,所以可以采用链表来维护这个数列,同时在插入堆中时绑定链表节点的编号,此时操作即改为合并三个链表元素,标记堆中三个元素不合法,执行\(K\)次即可选出合法的\(K\)段间距,即\(K\)个点对。

\(\\\)

\(Code\)


#include<cmath>
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define R register
#define gc getchar
#define N 100010
#define inf 1000000000
using namespace std; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} bool vis[N];
int n,m,ans,pre[N],nxt[N],num[N];
priority_queue<pair<int,int> > q; int main(){
n=rd(); m=rd();
for(R int i=2,lp=rd(),now;i<=n;++i){
pre[i]=i-1; nxt[i]=i+1;
num[i]=(now=rd())-lp; lp=now;
}
pre[2]=nxt[n]=0;
for(R int i=2;i<=n;++i) q.push(make_pair(-num[i],i));
while(m--){
while(vis[q.top().second]) q.pop();
int now=q.top().second;
int pr=pre[now],nx=nxt[now];
q.pop(); ans+=num[now];
pre[nxt[now]=nxt[nx]]=now;
nxt[pre[now]=pre[pr]]=now;
num[now]=(pr&&nx)?min(inf,num[pr]+num[nx]-num[now]):inf;
vis[pr]=vis[nx]=1; q.push(make_pair(-num[now],now));
}
printf("%d\n",ans);
return 0;
}

\(\\\)

种树就是把链表循环起来选最大,循环的关系不需要考虑边界的特判比上面的还水

\(\\\)

#include<cmath>
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define R register
#define gc getchar
#define N 200010
#define inf 1000000000ll
using namespace std;
typedef long long ll; inline ll rd(){
ll x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} bool vis[N];
ll n,m,ans,pre[N],nxt[N],num[N];
priority_queue<pair<int,int> > q; int main(){
n=rd(); m=rd();
if(n<m*2){puts("Error!");return 0;}
for(R ll i=1;i<=n;++i){
pre[i]=i-1; nxt[i]=i+1;
num[i]=rd();
}
pre[1]=n; nxt[n]=1;
for(R ll i=1;i<=n;++i) q.push(make_pair(num[i],i));
while(m--){
while(vis[q.top().second]) q.pop();
ll now=q.top().second;
ll pr=pre[now],nx=nxt[now];
q.pop(); ans+=num[now];
pre[nxt[now]=nxt[nx]]=now;
nxt[pre[now]=pre[pr]]=now;
num[now]=min(inf,num[pr]+num[nx]-num[now]);
vis[pr]=vis[nx]=1; q.push(make_pair(num[now],now));
}
printf("%lld\n",ans);
return 0;
}

[ CTSC 2007 / BZOJ 2151 ] Backup / 种树的更多相关文章

  1. [bzoj 2151]种树(贪心)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2151 分析:原型是bzoj 1150(CTSC 2007) 首先DP无法下手,想到贪心.想到贪 ...

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

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

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

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

  4. P3620 [APIO/CTSC 2007]数据备份

    P3620 [APIO/CTSC 2007]数据备份 题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同 ...

  5. 洛谷 P3620 [APIO/CTSC 2007]数据备份 解题报告

    P3620 [APIO/CTSC 2007]数据备份 题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同 ...

  6. 【BZOJ 2151】 2151: 种树 (贪心+堆+双向链表)

    2151: 种树 Description A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n.并且每个 ...

  7. 【刷题】BZOJ 2151 种树

    Description A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树.园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n.并且每个位置都有一个美观度 ...

  8. BZOJ 2151 种树(循环链表)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2151 [题目大意] 在一个长度为n的数字环中挑选m个不相邻的数字使得其和最大 [题解] ...

  9. bzoj 2151 种树——贪心+后悔

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2151 似乎是半年+前讲过的.(然而看到的时候却不会了) 考虑贪心,限制就是不能选两边的.如果 ...

随机推荐

  1. WIKIOI 1319 玩具装箱

    1319 玩具装箱 题目描述 Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维 ...

  2. 轰炸III(codevs 1830)

    题目背景 一个大小为N*M的城市遭到了X次轰炸,每次都炸了一个每条边都与边界平行的矩形. 题目描述 在轰炸后,有Y个关键点,指挥官想知道,它们有没有受到过轰炸,如果有,被炸了几次,最后一次是第几轮. ...

  3. 【BZOJ3238】差异(后缀数组,单调栈)

    题意: 思路:显然len(t[i])+len(t[j])这部分的和是一定的 那么问题就在于如何快速求出两两之间lcp之和 考虑将它们排名后用SA可以很方便的求出lcp,且对答案没有影响,因为形式都是数 ...

  4. BZOJ5089: 最大连续子段和

    维护一个序列支持以下操作:区间加,区间求最大子段和.n<=50000,m<=50000. 我TM再也不写分块了... 先分块,对于块整体加的操作,假设块里面有若干二元组(x,y),表示一个 ...

  5. IBOutlet loadView UIButton的subview数量 UIWebView

    IBOutlet声明的插座变量和属性一起使用的时候,在.m文件调用的是属性. 在loadView方法中获取view属性会产生循环引用问题并导致内存溢出. Control+E到行尾,Control+A到 ...

  6. 试来试去,WIN下最简单的WIN API开发工具,Pelles C就好啦

    昨晚试过N个,不是太大,就是不容易和WIN API集成. 今早一试就灵了个.... Pelles C. Pelles C是一款windows下的C IDE,支持调试,且为免费.它有一个高效率的链接器, ...

  7. JRobin cpu 和 磁盘

    https://blog.csdn.net/li_zhongnan/article/details/3754053 https://blog.csdn.net/li_zhongnan/article/ ...

  8. Angularjs中添加HighCharts

    一. 添加基本配置 1. 添加指令 angular.module('newApp') .directive('dpHighchart', ['$rootScope', function($rootSc ...

  9. 推断client手机类型,并跳转到对应的app下载页面

    实现的原理,是检測浏览器的 USER-AGENT 这个header,然后依据正則表達式来确定client类型. 假设都不匹配,Fallback回退策略是显示相应的页面.让用户自己选择. 适合採用二维码 ...

  10. 一个unity3d lightmap问题

    上周美术同学在使用unity3d制作lightmap的过程中,发现部分被lightmap影响的模型在移动端上效果与pc端不一致.当时我大概看了下,分析后,得到一个结论是“在移动端上lightmap的h ...