使用优先队列,可以快速取出重量最小的果堆以使用。
本题需要从重量最小的果堆开始选取,若该重量的果堆个数为单数,则让多余的那个果堆与重量第二小的果堆合并;若该重量的果堆个数为复数,则自己内部消化。
下面是代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> st;
int n;
cin>>n;
for(int i=1;i<=n;i++){
int c,w;
cin>>c>>w;
st.push({w,c});
}
int f=0,pre=0,ans=0;//f判断上轮合并后是否存在多余的1个果堆,pre为多余的那个果堆的重量
while(!st.empty()){
pair<int,int>x=st.top();//取个体重量最小的果堆
st.pop();
int q=0,cnt=x.second;//q为合并后的重量,cnt为果堆的个数
if(f!=0)//上轮合并后存在多余1个果堆
{
cnt--;//从果堆x中取出一个,与多余果堆合并
q=pre+x.first;
ans+=q;
st.push({q,1});
f=0;//多余果堆已被合并,不存在多余果堆了
}
if(f==0)//不存在多余的果堆
{
q=2*x.first;//两个相同的果堆合并
if(cnt%2==1)//若果堆数量为单数,本轮合并后会存在多余的1个果堆
{
f=1;//标记存在多余1个果堆
pre=x.first;
}
ans+=(cnt/2)*q;
if(cnt/2!=0)//若果堆x的个数>=2
{
st.push({q,cnt/2});
}
}
}
int mod=1e9+7;
cout<<ans%mod<<endl;
}

京公网安备 11010502036488号