题目解析
这道题目是一个哈夫曼编码问题,也被称为合并果子问题。核心在于利用贪心策略和优先队列(小根堆)来寻找最小的合并代价
我们应该总是优先合并当前重量最小的两堆果子。 为了高效地找到当前最小的两堆果子,我们需要使用优先队列,并且需要将其设置为小根堆(即堆顶元素最小)
代码演示
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define endl '\n'
const int N = 500010;
const int mod=1000000007;
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
void solve(){
int n,c,w,total=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>c>>w;
q.push({w,c});
total+=c;
}
if(total<=1){
cout<<"0"<<endl;
return;
}
int sum=0;
// while(total>1){
// pair<int,int>pii=q.top();
// q.pop();
// if(pii.second>=2){
// int tmp1=pii.second/2;
// sum+=2*tmp1*pii.first;
// sum%=mod;
// q.push({2*pii.first,tmp1});
// int tmp2=pii.second%2;
// if(tmp2==1){
// q.push({pii.first,1});
// }
// total-=tmp1;
// }else{
// pair<int,int>pii2=q.top();
// q.pop();
// pii2.second--;
// sum+=pii.first+pii2.first;
// sum%=mod;
// q.push({pii.first+pii2.first,1});
// if(pii2.second>0){
// q.push({pii2.first,pii2.second});
// }
// total--;
// }
// }
while(total>1){
auto [w,c]=q.top();
q.pop();
if(c>=2){
int tmp1=c/2;
sum+=2*w*tmp1;
q.push({2*w,tmp1});
if(c%2){
q.push({w,1});
}
total-=tmp1;
}else{
auto [w2,c2]=q.top();
q.pop();
c2--;
sum+=w+w2;
q.push({w+w2,1});
if(c2){
q.push({w2,c2});
}
total--;
}
}
sum%=mod;
cout<<sum<<endl;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int T=1;//cin>>T;
while(T--){
solve();
}
return 0;
}

京公网安备 11010502036488号