【做题记录】CF1428E Carrots for Rabbits—堆的妙用
生活随笔
收集整理的這篇文章主要介紹了
【做题记录】CF1428E Carrots for Rabbits—堆的妙用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
CF1428E Carrots for Rabbits
題意:
有 \(n\) 個蘿卜,每個蘿卜的初始大小為 \(a_i\) 。現在要把這些蘿卜切為為 \(k\) 個。吃每一個蘿卜的時間為這個蘿卜的大小的平方,求吃完所有蘿卜的最小時間,即 \(\sum_{i=1}^{k}{a_i^2}\) 最小 。求出最小值 。
題解:
-
二分是錯的 。
-
貪心切兩段是錯的 。
正解:
令 \(f(i,cnt)\) 為把第 \(i\) 個蘿卜分為 \(cnt\) 個后吃完的最少時間,則初始答案為 \(\sum_{i=1}^{n}{f(i,1)}\) 。
維護一個小根堆,存的值為 \(f(i,cnt)-f(i,cnt+1)\) ,每一次取出堆頂,將堆頂的蘿卜再切一段下來,并塞回堆中 。
在這一次操作中,答案減小了 \(f(i,cnt)-f(i,cnt+1)\) ,且這個值在這一次切割操作中是最優的,所以答案是正確的。
以上操作進行 \(k-n\) 次 。
最終的答案為初始答案減去每一次取出堆頂后對答案減小的值。
大致代碼:
int n,k,a[Maxn]; ll ans; ll f(ll sum,ll cnt) {return (sum%cnt)*(sum/cnt+1ll)*(sum/cnt+1ll)+(cnt-(sum%cnt))*(sum/cnt)*(sum/cnt); } struct Data {ll sum,cnt;bool friend operator < (Data x,Data y){return (f(x.sum,x.cnt)-f(x.sum,x.cnt+1ll))<(f(y.sum,y.cnt)-f(y.sum,y.cnt+1ll));} }; priority_queue<Data> q; // main n=rd(),k=rd(); for(int i=1;i<=n;i++) a[i]=rd(),q.push((Data){1ll*a[i],1ll}),ans+=1ll*a[i]*a[i]; for(int i=1;i<=k-n;i++) {Data cur=q.top(); q.pop();ans-=(f(cur.sum,cur.cnt)-f(cur.sum,cur.cnt+1ll)),cur.cnt+=1ll;q.push(cur); } printf("%lld\n",ans);總結
以上是生活随笔為你收集整理的【做题记录】CF1428E Carrots for Rabbits—堆的妙用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实现电脑和单片机通信单片机如何与电脑相连
- 下一篇: 【做题记录】区间排序—线段树