Luogu [P1334] 瑞瑞的木板(手写堆)
Posted 青珹
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu [P1334] 瑞瑞的木板(手写堆)相关的知识,希望对你有一定的参考价值。
其实这个题完全不需要用手写堆,只需要一遍遍sort就行了……
但是!
为了练习手写堆,还是用手写堆做了。
在做本题之前,如果你没有什么思路的话,建议先做Luogu的合并果子。
好,假设你已经做过了合并果子了。那么正式开始本题:
相信许多人都已经知道了这道题就是合并果子,但是还不知道它是怎样转化成合并果子的,其实很简单:比如说9 7 6 5 3,有些同学可能会想:每次我砍最大的,然后剩下的不就少了。其实不然,因为不一定一次只能砍一个,可以砍两个或两个以上。不多说,我把上面例子的最优策略讲出来大概就知道了。step1:把9+7+6+5+3切成7+6和5+3+9两部分;step2:把7+6切成7和6;step3:把5+3+9切成5+3和9两部分:step4:把5+3切成5和3。这时我们再回过头来看,是不是就是合并果子的步骤?
AC代码:
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; long long x,n,tot,dl[100001],sum;//小根堆 char c; void delete_2(long long num) { if(((num<<1)+1)<=tot) { if(dl[num<<1]<dl[(num<<1)+1]) { if(dl[num]<dl[num<<1]) return ; else { swap(dl[num],dl[num<<1]); delete_2(num<<1); } } else { if(dl[num]<dl[(num<<1)+1]) return ; else { swap(dl[num],dl[(num<<1)+1]); delete_2((num<<1)+1); } } } else { if((num<<1)<=tot) { if(dl[num]<dl[num<<1]) return ; else { swap(dl[num],dl[num<<1]); delete_2(num<<1); } } else return ; } return ; } void delete_1()//删除操作 { dl[1]=dl[tot--]; delete_2(1); } void qcr(long long num) //名字随便取的 { if(num==1) return ; if(dl[num]<dl[num>>1]) { swap(dl[num],dl[num>>1]); num>>=1; qcr(num); } return ; } void putin(long long x) //添加操作 { dl[++tot]=x; qcr(tot); } void putout() //读取操作 { printf("%d",dl[1]); return ; } int main() { ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++) { cin>>x; putin(x); } for(int i=1;i<n;i++) { int q,p; q=dl[1]; delete_1(); p=dl[1]; delete_1(); sum+=p+q; putin(p+q); } cout<<sum; return 0; }
以上是关于Luogu [P1334] 瑞瑞的木板(手写堆)的主要内容,如果未能解决你的问题,请参考以下文章