[CTSC2007]数据备份Backup 题解
题意:
一维直线上有n个点,任取2k个互不相同的点组成k条链,求链的最小总长
思路:
1.最优时链不相交,相邻两两相减,将题目转化为:在n-1个数中取互不相邻的k个数使总和最小。
2.贪心取最小的“数”(设为a[x])累加(表示已经取了),再建立一个“反悔机制”(可能和网络流相似):将a[x]向两边各拓展一个,合并成为新的“数”,其值为两边之和减去a[x](取这段则可以等同不取a[x]而取其它),再将a[x]和其两边的删掉。这样可以保证最优,同时也可保证取的数不相邻(未被删去的段的两端都没有被取到)
3.用堆维护最小值,用双向链表实现向两边拓展。注意边界:当某一a[x]的一端无法拓展时,则显然拓展不如当前优,将可拓展的一端删去,防止被取相邻两个数。
反思:
堆的基本操作不是很熟悉,同时用编号映射有点绕。
代码:
#include<cstdio>
const int M=;
#define swap(x,y) o=x,x=y,y=o
int n,m,t,o,sum,a[M],id[M],di[M],pre[M],nex[M];
//堆中第i个点在读入时的编号为id[i] 读入时的第i个点在堆中的编号为di[i]
//pre[] nex[]中存的是读入时的编号读入时的编号,下标也为读入时的编号 void up(int x)
{
for (;a[id[x]]<a[id[x>>]] && x>;x=x>>)
swap(di[id[x]],di[id[x>>]]),swap(id[x],id[x>>]);
} void down(int x)
{
for (int y=x<<;y<=t;)
{
if (y<t && a[id[y]]>a[id[y|]]) ++y;
if (a[id[x]]>a[id[y]])
swap(di[id[x]],di[id[y]]),swap(id[x],id[y]),x=y,y=x<<;
else break;
}
} void add(int x) { id[++t]=x,up(di[x]=t); }
void del(int x) { id[di[x]]=id[t],up(di[id[t--]]=di[x]),down(di[x]); } int read()
{
int x=; char ch=getchar();
while (ch< || ch>) ch=getchar();
while (ch> && ch<) x=(x<<)+(x<<)+ch-,ch=getchar();
return x;
} int main()
{
int n=read(),m=read(),i,x;
for (i=;i<=n;++i) a[i]=read();
for (i=;i<n;++i) a[i]=a[i+]-a[i],pre[i]=i-,nex[i]=i+,add(i);
for (;m--;)
{
sum=sum+a[x=id[]];
if (!pre[x] && nex[x]==n) break;
del(x);
if (!pre[x]) del(nex[x]),pre[nex[nex[x]]]=;
else if (nex[x]==n) del(pre[x]),nex[pre[pre[x]]]=n;
else
{
del(pre[x]),del(nex[x]);;
a[x]=a[pre[x]]+a[nex[x]]-a[x],add(x);
nex[pre[x]=pre[pre[x]]]=pre[nex[x]=nex[nex[x]]]=x;
}
}
printf("%d\n",sum);
return ;
}
[CTSC2007]数据备份Backup 题解的更多相关文章
- 【链表】bzoj 1150: [CTSC2007]数据备份Backup
1150: [CTSC2007]数据备份Backup Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1136 Solved: 458[Submit] ...
- bzoj1150 [CTSC2007]数据备份Backup 双向链表+堆
[CTSC2007]数据备份Backup Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2727 Solved: 1099[Submit][Stat ...
- 【BZOJ1150】[CTSC2007]数据备份Backup 双向链表+堆(模拟费用流)
[BZOJ1150][CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此 ...
- BZOJ1150 [CTSC2007]数据备份Backup 链表+小根堆
BZOJ1150 [CTSC2007]数据备份Backup 题意: 给定一个长度为\(n\)的数组,要求选\(k\)个数且两两不相邻,问最小值是多少 题解: 做一个小根堆,把所有值放进去,当选择一个值 ...
- 1150: [CTSC2007]数据备份Backup
1150: [CTSC2007]数据备份Backup https://lydsy.com/JudgeOnline/problem.php?id=1150 分析: 堆+贪心. 每次选最小的并一定是最优的 ...
- 【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列+双向链表)
1150: [CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设 ...
- 【bzoj1150】[CTSC2007]数据备份Backup 模拟费用流+链表+堆
题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏 ...
- BZOJ1150 [CTSC2007]数据备份Backup 【堆 + 链表】
题目 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的 ...
- [CTSC2007]数据备份Backup (贪心)
题面 Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐 ...
随机推荐
- 508 Most Frequent Subtree Sum 出现频率最高的子树和
详见:https://leetcode.com/problems/most-frequent-subtree-sum/description/ C++: /** * Definition for a ...
- Spark MLlib编程API入门系列之特征提取之主成分分析(PCA)
不多说,直接上干货! 主成分分析(Principal Component Analysis,PCA), 将多个变量通过线性变换以选出较少个数重要变量的一种多元统计分析方法. 参考 http://blo ...
- json数组某个数值对应渲染
当你统计某一年的某个值它对应的月份总数时,后台没有直接处理好,某个月对应某个值,这样会增加统计的负担,但当数据时这样的时候,在angularjs中时不能直接引用的. "data": ...
- Java_面向对象中的this和super用法
this: 1.使用在类中,可以用来修饰属性.方法.构造器 2.表示当前对象或者是当前正在创建的对象 3.当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加 this 来表明该变量时类成 ...
- Hive工具类
Hive2.x的工具类,对常用方法进行了封装,其中设置了kerberos认证. package com.ideal.template.openbigdata.util; import java.sql ...
- UVA 11922 Permutation Transformer (Splay树)
题意: 给一个序列,是从1~n共n个的自然数,接下来又m个区间,对于每个区间[a,b],从第a个到第b个从序列中分离出来,翻转后接到尾部.输出最后的序列. 思路: 这次添加了Split和Merge两个 ...
- C++#pragma pack指令
微软官方文档说#pragma pack 指令的作用是为结构.联合和类成员指定 pack 对齐.的主要作用就是改变编译器的内存对齐方式,这个指令在网络报文的处理中有着重要的作用,#pragma pack ...
- Android接入支付宝和微信支付
然后把下载下来的aar包,放到项目目录下面的libs目录下,通过下面的gradle依赖进来 // 支付宝 SDK AAR 包所需的配置compile(name: 'alipaySdk-15.6.0-2 ...
- Java中wait()方法为什么要放在同步块中?(lost wake-up 问题)
问题起源 事情得从一个多线程编程里面臭名昭著的问题"Lost wake-up problem"说起. 这个问题并不是说只在Java语言中会出现,而是会在所有的多线程环境下出现. 假 ...
- Wow64
翻译自Wikipedia: WoW64 运行在微软平台上,WoW64(Windows 32-bit on Windows 64-bit) 是一个Windows的子操作系统, 它能运行32位的应用,在所 ...