[A/C 2007] 数据备份(网络流,堆)

给你N各点的位置和K条链,需要用这些链把2K个点连起来,使得链的总长最短。可以随意选择要链的点。n=100000。

这道题居然可以用堆……

首先,不能把区间一股脑加进去,因为有点可能会被重复连接。处理方法是这样的:若选择了第i个区间,那就把i,区间i-1和区间i+1都删除了,然后加入一个新区间,和左右区间相连接,并且将当前区间的值改为\(len[i-1]+len[i+1]-len[i]\)。这样如果再选这个区间,就相当于把区间i撤消了。

具体证明嘛,见这个blog,讲道理我是不想看。。

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include <cstdio>
using namespace std; typedef long long LL;
const LL maxn=1e5+5, INF=1e18;
LL n, k, a[maxn];
struct Node{
Node(LL x=0, LL y=0){ v=x; chain=y; }
LL v, chain;
}node[maxn]; //维护链长的最小堆
bool operator <(Node &a, Node &b){ return a.v<b.v; }
LL cntnode, cntc, ans;
struct Chain{
LL l, r, len, node;
}c[maxn], tmpl, tmpr; //以左端点编号.len表示长度.node表示堆中的哪个点 void swap(LL &x, LL &y){ LL t=x; x=y; y=t; }
void swap(LL x, LL y){ //传进来的是堆中点的编号
c[node[x].chain].node=y;
c[node[y].chain].node=x;
Node tmp=node[x]; node[x]=node[y]; node[y]=tmp;
} void ins(LL now){
while (now!=1){
if (node[now]<node[now>>1])
swap(now, now>>1), now>>=1;
else break;
}
} void del(LL now){ //只是清零并移到最后
if (now==0) return;
node[now].v=INF; LL p;
while ((now<<1)<=cntnode){
if (now<<1==cntnode||node[now<<1].v<node[now<<1|1].v) p=0; else p=1;
swap(now, now<<1|p), now=now<<1|p;
}
} int main(){
scanf("%lld%lld", &n, &k);
for (LL i=1; i<=n; ++i) scanf("%lld", &a[i]);
for (LL i=1; i<n; ++i){
c[i].l=i-1; c[i].r=i+1; ++cntc;
node[++cntnode].v=c[i].len=a[i+1]-a[i];
node[cntnode].chain=i; c[i].node=cntnode; ins(cntnode);
}
c[0].len=c[n].len=INF;
for (LL i=1; i<=k; ++i){
Chain &tmp=c[node[1].chain]; //选定长度最小的链
tmpl=c[tmp.l]; tmpr=c[tmp.r]; //和它旁边的两条链
ans+=tmp.len;
del(1); del(c[tmp.l].node); del(c[tmp.r].node); //把这三个链代表的点从堆里面删掉
c[tmpl.l].r=tmpl.r; c[tmpr.r].l=tmpr.l; //把原来的链变成合并后的链
tmp.l=tmpl.l; tmp.r=tmpr.r;
tmp.len=tmpl.len+tmpr.len-tmp.len;
node[tmp.node].v=tmp.len; //把原来的点变成新点
ins(tmp.node);
}
printf("%lld\n", ans);
return 0;
}

自己还是太NAIVE了,其实根本就不需要从外部访问堆的说,下面这个大神代码就没有用,用的是stl里面的优先队列orz。

只要不用外部访问堆,都可以用stl~

#include<iostream>
#include<cstdio>
#include<queue>
#define INF 2000000000
#define MN 100000
#define pa pair<long long,int>
#define mp make_pair
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
return x*f;
} long long ans=0;
int n,k,ne[MN+5],la[MN+5],a[MN+5],len[MN+5];
bool del[MN+5];
priority_queue<pa,vector<pa>,greater<pa> > q; int main()
{
n=read();k=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n+1;i++)la[i+1]=i,ne[i]=i+1;
la[1]=0;ne[n+1]=0;
for(int i=2;i<=n;i++)
q.push(mp(len[i]=a[i]-a[i-1],i));
len[1]=len[n+1]=INF;
for(int i=1;i<=k;i++)
{
while(del[q.top().second])q.pop();
ans+=q.top().first;int x=q.top().second;q.pop();
int a=la[x],b=ne[x];
del[a]=del[b]=1;
q.push(mp(len[x]=len[a]+len[b]-len[x],x));
la[x]=la[a];ne[x]=ne[b];
ne[la[a]]=x;la[ne[b]]=x;
}
cout<<ans;
return 0;
}

[A/C 2007] 数据备份(网络流,堆)的更多相关文章

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

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

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

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

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

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

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

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

  5. [APIO/CTSC 2007]数据备份(贪心+堆)

    你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣. ...

  6. 洛谷P3620 [APIO/CTSC 2007] 数据备份 [堆,贪心,差分]

    题目传送门 题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽 ...

  7. [luogu3620][APIO/CTSC 2007]数据备份【贪心+堆+链表】

    题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏 ...

  8. 题解:[APIO/CTSC 2007]数据备份

    你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣.已 ...

  9. P3620 [APIO/CTSC 2007]数据备份[优先队列+贪心]

    题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏 ...

随机推荐

  1. Day2-Python基础2---集合和文件操作

    一.集合操作 集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变成集合,就自动去重了 关系测试,测试两组数据之前的交集.差集.并集等关系 s = set([1,4,5,7,3, ...

  2. Java-API-Package:org.springframwork.transaction.annotation

    ylbtech-Java-API-Package:org.springframwork.transaction.annotation 1.返回顶部 1. @NonNullApi @NonNullFie ...

  3. 转:面对一个全新的环境,作为一个Oracle DBA,首先应该了解什么

    转载:面对一个全新的环境,作为一个Oracle DBA,首先应该了解什么 由于时间比较久了,找不到原文章的链接,先贴上内容供大家参考 在这里,不谈那些大的方面,比如了解整个IT环境整体情况,假设你已经 ...

  4. 侯捷STL学习(12)--STL相关内容hash+tuple

    layout: post title: 侯捷STL学习(12) date: 2017-08-01 tag: 侯捷STL --- 第四讲 STL相关的内容 Hash Function 将hash函数封装 ...

  5. pycharm中 unittests in xxxx 运行模式

    pycham中 当你运行时 ,使用的 是  Run "unittests in  xxxx" 模式时候,if __name__ == '__main__':  后面的代码是不执行的 ...

  6. [更新中]【fit-flow使用总结】djang开发中git flow使用总结

    djang开发中git flow使用总结 初次接触可以先看看此链接上关于git flow的东西http://danielkummer.github.io/git-flow-cheatsheet/ind ...

  7. hibernate 延长加载范围

    1. 关闭延迟加载功能 lazy="false"2.修改抓取策略 fetch="join"直接查询关联数据,一个联接查询搞定3.使用Hibernate对象的in ...

  8. Java8 日期和时间实用技巧

    新的日期API ZoneId: 时区ID,用来确定Instant和LocalDateTime互相转换的规则 Instant: 用来表示时间线上的一个点 LocalDate: 表示没有时区的日期, Lo ...

  9. Dataguard ORA-19909 ORA-01110

    在创建ORACLE 10G Dataguard时,报错: Datafile 1 (ckpscn 24967685451) is orphaned on incarnation#=6 MRP0: Bac ...

  10. 【265】shell文件创建链接

    优点:可以在其他文件夹内运行对应的*.sh文件,例如通过putty会默认进入的文件夹,可以将链接文件放在那里,就可以直接调用了! 方法:很简单 1. 在文件上点击右键>创建链接 2. 可以对下面 ...