bzoj 1150 贪心
首先选取的线段一定是相邻两个端点线段,那么我们贪心的考虑这个问题,我们先在这n-1条线段中选出最短的一条,然后将这条线段的值改为左面的线段的值+右面的线段的值-自己的值,用这条线段取代原来这三条线段,继续做,那么这个取m次出来之后的就是答案,对于证明,我们可以大概的去想,选了新的线段代表不选这条原本的线段,然后选另两条相邻的线段,这样选的线段的条数只是+1,相当于又取了一条线段,正确性的证明可以大概感知。
至于选最小的用堆来维护就行了,因为需要删除精确到点编号,对堆用的不熟悉,所以用sbt代替。
/**************************************************************
Problem:
User: BLADEVIL
Language: Pascal
Result: Accepted
Time: ms
Memory: kb
****************************************************************/ //By BLADEVIL
type
pointer=^rec;
rec =record
pred, succ :pointer;
num, fuck :int64;
end;
shit =record
shit1, shit2 :longint;
end; var
n, m :longint;
a :array[..] of pointer;
left, right, size :array[..] of longint;
key, adr :array[..] of longint;
t, tot :longint;
ans :int64; procedure left_rotate(var t:longint);
var
k :longint;
begin
k:=right[t];
right[t]:=left[k];
left[k]:=t;
size[k]:=size[t];
size[t]:=size[left[t]]+size[right[t]]+;
t:=k;
end; procedure right_rotate(var t:longint);
var
k :longint;
begin
k:=left[t];
left[t]:=right[k];
right[k]:=t;
size[k]:=size[t];
size[t]:=size[left[t]]+size[right[t]]+;
t:=k;
end; procedure maintain(var t:longint;flag:boolean);
begin
if not flag then
begin
if size[left[left[t]]]>size[right[t]] then
right_rotate(t) else
if size[right[left[t]]]>size[right[t]] then
begin
left_rotate(left[t]);
right_rotate(t);
end else exit;
end else
begin
if size[right[right[t]]]>size[left[t]] then
left_rotate(t) else
if size[left[right[t]]]>size[left[t]] then
begin
right_rotate(right[t]);
left_rotate(t);
end else exit;
end;
maintain(left[t],false);
maintain(right[t],true);
maintain(t,true);
maintain(t,false);
end; procedure insert(var t:longint;v,k:int64);
begin
if t= then
begin
inc(tot);
t:=tot;
left[t]:=;
right[t]:=;
size[t]:=;
key[t]:=v;
adr[t]:=k;
end else
begin
inc(size[t]);
if v<key[t] then insert(left[t],v,k) else
if v>key[t] then insert(right[t],v,k) else
if v=key[t] then
if k>adr[t] then insert(right[t],v,k) else
insert(left[t],v,k);
maintain(t,v>=key[t]);
end;
end; function delete(var t:longint;v,k:int64):shit;
var
damn :shit;
begin
dec(size[t]);
if (v=key[t]) and (k=adr[t]) or (v>key[t]) and (right[t]=) or (v<key[t]) and (left[t]=) then
begin
delete.shit1:=key[t];
delete.shit2:=adr[t];
if (left[t]=) or (right[t]=) then
t:=left[t]+right[t] else
begin
damn:=delete(left[t],v+,k);
key[t]:=damn.shit1;
adr[t]:=damn.shit2;
end;
end else
if v<key[t] then delete:=delete(left[t],v,k) else
if v>key[t] then delete:=delete(right[t],v,k) else
if v=key[t] then
if k>adr[t] then delete:=delete(right[t],v,k) else
if k<adr[t] then delete:=delete(left[t],v,k);
end; function mini(var t:longint):longint;
begin
if left[t]= then exit(adr[t]) else exit(mini(left[t]));
end; procedure init;
var
i :longint;
null :pointer; begin
read(n,m);
for i:= to n do
begin
new(null);
a[i]:=null;
read(a[i]^.num);
end;
for i:=n downto do a[i]^.num:=a[i]^.num-a[i-]^.num;
a[]^.num:=;
for i:= to n do
begin
if i= then a[i]^.pred:=a[n] else a[i]^.pred:=a[i-];
if i=n then a[i]^.succ:=a[] else a[i]^.succ:=a[i+];
end;
for i:= to n do a[i]^.fuck:=i;
end; procedure main;
var
i :longint;
x :longint;
begin
t:=;
for i:= to n do insert(t,a[i]^.num,i);
for i:= to m do
begin
x:=mini(t);
ans:=ans+a[x]^.num;
delete(t,a[x]^.num,a[x]^.fuck);
delete(t,a[x]^.pred^.num,a[x]^.pred^.fuck);
delete(t,a[x]^.succ^.num,a[x]^.succ^.fuck);
a[x]^.num:=a[x]^.pred^.num+a[x]^.succ^.num-a[x]^.num;
insert(t,a[x]^.num,x);
a[x]^.pred^.pred^.succ:=a[x];
a[x]^.pred:=a[x]^.pred^.pred;
a[x]^.succ^.succ^.pred:=a[x];
a[x]^.succ:=a[x]^.succ^.succ;
end;
writeln(ans);
end; begin
init;
main;
end.
bzoj 1150 贪心的更多相关文章
- [BZOJ 1150] [CTSC2007] 数据备份Backup 【贪心 + 链表】
题目链接:BZOJ - 1150 题目分析 可以看出,我们选的 k 条边一定是相邻两点之间的线段.我们可以将每条边看成一个点,那么我们就是要在 n-1 个点中选出互不相邻的 k 个,使它们的和最小. ...
- 【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列+双向链表)
1150: [CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设 ...
- BZOJ 1150 [CTSC2007]数据备份Backup(贪心+优先队列)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1150 [题目大意] 给出n个数,请你挑出k对(每个数不可重复选取),使得他们差的绝对值 ...
- bzoj 1150&2151&2288(双向链表+堆)(贪心)
经典模型:在n个点中选k个点,要求两两不相邻,且总权值最大/最小. 做法:用双向链表串起来,把所有点丢进堆里,选择一个点的时候把它左右两个点从双向链表和堆中去除,然后把这个点的权值加进ans,出堆后改 ...
- 【链表】bzoj 1150: [CTSC2007]数据备份Backup
1150: [CTSC2007]数据备份Backup Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1136 Solved: 458[Submit] ...
- 【BZOJ 1150】[CTSC2007]数据备份Backup
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 选择的连接肯定是相邻的点对. 那么我们处理出来长度为n-1的数组a 其中a[i-1] = dis[i]-dis[i-1] 那么问题就 ...
- bzoj 1193 贪心
如果两点的曼哈顿距离在一定范围内时我们直接暴力搜索就可以得到答案,那么开始贪心的跳,判断两点横纵坐标的差值,差值大的方向条2,小的条1,不断做,直到曼哈顿距离较小时可以暴力求解. 备注:开始想的是确定 ...
- bzoj 2697 贪心
就贪心就行了,首先可以看成n个格子,放物品,那么 一个物品假设放3个,放在1,k,n处,那么价值和放在1,n 是一样的,所以一个物品只放两个就行了,价值大的应该尽量放 在两边,那么排序之后模拟就行了 ...
- bzoj 3037 贪心
我们可以贪心的分析,每个点的入度如果是0,那么这个点不可能 被用来更新答案,那么我们每次找入度为0的点,将他去掉,如果他连的 点没有被更新过答案,那么更新答案,去掉该点,环的时候最后处理就行了 /** ...
随机推荐
- HDFS常用文件操作
put 上传文件 hadoop fs -put wordcount.txt /data/wordcount/ text 查看文件内容 hadoop fs -text /output/wo ...
- ubuntu安装显卡驱动和cuda
NVIDIA-linux.run安装后,会出现登录页面循环,解决办法是在运行命令后加入-no-opengl-files 打开nvidia x server Settings软件,显示:You do n ...
- gcc6.3编译c++11的程序链接opencv时字符型函数未定义
在Windows下编写图像处理程序,由于要使用regex,升级了mingw,编译c++11代码.之前代码中使用了opencv2.4.10,一直运行良好,升级编译器以后发现了错误:undefined r ...
- vue.js的特点-1
1. Vue.js是数据驱动的,无需手动操作DOM. 它通过一些特殊的HTML语法,将DOM和数据绑定起来.一旦你创建了绑定,DOM将和数据保持同步,每当变更了数据,DOM也会相应的更新. 2. MV ...
- SSH面试集锦——不看后悔哦!
1. 谈谈你mvc的理解 MVC是Model-View-Controler的简称.即模型-视图-控制器.MVC是一种设计模式,它强制性的把应用程序的输入.处理和输出分开. MVC中的模型 ...
- ashx文件和aspx
ashx文件和aspx文件有什么不同? 我们先新建一个ashx文件看看: <%@ WebHandler Language="C#" Class="Handler&q ...
- Flash by sshockwave [树dp]
题目 给定一棵树,每个点有一个活动时间,长度为正整数$t_i$ 你需要安排每个点的活动时间什么时候开始什么时候结束,并且满足:任何一个时刻没有两个相邻的点都在活动 开始时刻为0,在以上条件下最小化所有 ...
- [51nod1791] 合法括号子段 DP
---题面--- 题解: 首先我们需要发现一个性质,在括号序列不变的情况下,括号匹配是不会变的,因此不论子串怎么取,括号匹配的关系是不会变化的.这是一个很容易发现的性质,然而我太弱,没发现. 于是可以 ...
- 02.Java面向对象问题
目录介绍 2.0.0.1 重载和重写的区别?重载和重写绑定机制有何区别?父类的静态方法能否被子类重写? 2.0.0.2 封装.继承.多态分别是什么? 2.0.0.3 接口和抽象类的区别是什么?接口的意 ...
- 某ISP的流氓行径 劫持用户HTTP请求插入js代码
最近公司搞的项目有用户反应点击任意链接后偶尔会跳到一个“莫名奇妙”的网站………… 喏,就是这个咯.