博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 2151: 种树【贪心+堆】
阅读量:4577 次
发布时间:2019-06-08

本文共 1459 字,大约阅读时间需要 4 分钟。

和数据备份差不多

设二元组(i,a[i]),开一个大根堆把二元组塞进去,以len排序,每次取出一个二元组
因为单纯的贪心是不行的,所以设计一个“反悔”操作。
记录二元组的前驱pr后继ne,把拿出来的二元组的len加进答案,然后把当前二元组和它的前驱后继当成一个,也就是len[x]=a[pr[x]]+a[ne[x]]-a[x],相应修改前驱后继,然后“删掉”前驱后继的二元组,这样的意思是如果再次选了修改过的二元组x,就意味着退还掉x,选择它的前驱后继,易证这样个数和ans都不会受影响。
至于用stl如何执行删除?可以把要的点的len设为inf,这样每次操作前先弹掉x与len[x]不符的点就相当于删除操作了。

#include
#include
#include
using namespace std;const int N=200005;int n,m,ans,a[N],pr[N],ne[N];struct qwe{ int p,v; qwe(int P=0,int V=0) { p=P,v=V; } bool operator < (const qwe &b) const { return v
q;int read(){ int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(p=='-') f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f;}int main(){ n=read(),m=read(); for(int i=1;i<=n;i++) { a[i]=read(); q.push(qwe(i,a[i])); pr[i]=i-1,ne[i]=i+1; } pr[1]=n,ne[n]=1; if(2*m>n) { puts("Error!"); return 0; } for(int i=1;i<=m;i++) { while(!q.empty()&&a[q.top().p]!=q.top().v) q.pop(); int x=q.top().p,l=pr[x],r=ne[x]; q.pop(); ans+=a[x]; pr[ne[x]=ne[r]]=x; ne[pr[x]=pr[l]]=x; a[x]=a[l]+a[r]-a[x]; a[l]=a[r]=1e9; q.push(qwe(x,a[x])); } printf("%d\n",ans); return 0;}

转载于:https://www.cnblogs.com/lokiii/p/9643243.html

你可能感兴趣的文章
微信公众平台开发2-access_token获取及应用(含源码)
查看>>
JavaScript数据结构-19.拓扑排序
查看>>
TeeChart取消3D
查看>>
oracle查看数据库版本和字符集
查看>>
mybatis调用mysql存储过程(返回值问题)
查看>>
InnoDB undo log物理结构的初始化
查看>>
linux常见问题集锦-2
查看>>
[转载]深入理解ASP.NET MVC之ActionResult
查看>>
Day74
查看>>
廖雪峰Java8JUnit单元测试-2使用JUnit-3参数化测试
查看>>
5个免费项目管理工具
查看>>
codeforces 502 g The Tree
查看>>
树的一些问题
查看>>
绑定bindchange事件的微信小程序swiper闪烁,抖动问题解决,(将微信小程序切换到后台一段时间,再打开微信小程序,会出现疯狂循环轮播,造成抖动现象)...
查看>>
用expect 实现切换用户时自动输入密码
查看>>
javascript 获取当前对象
查看>>
设计模式(三)---抽象工厂模式
查看>>
bzoj1061: [Noi2008]志愿者招募
查看>>
推荐一款开源、免费的标记语言转换工具,各种文档格式自由转换
查看>>
Erlang基础Mnesia 之应用场景(Why)
查看>>