由于优先队列和平衡树在时间复杂度上没有显著的差距,代码中全都用set代替的优先队列。
第k大的数
hdu4006
#include <bits/stdc++.h>
using namespace std;
const int N=20010;
int a[N];
int main(){
int n;
cin>>n;
multiset<int>se;
for( int i=0;i<n;i++){
scanf("%d",&a[i]);
se.insert(a[i]);
}
long long ans=0;
while(se.size()>1){
int x=*se.begin();
se.erase(se.begin());
int y=*se.begin();
se.erase(se.begin());
ans+=x+y;
se.insert(x+y);
}
cout<<ans<<endl;
return 0;
}
围栏修复
poj3253
逆向思维,将所有切好的木板重新拼成一块长木板
每次取堆中最小的两个元素,加在一起并且重新放回堆中
#include <bits/stdc++.h>
using namespace std;
const int N=20010;
int a[N];
int main(){
int n;
cin>>n;
multiset<int>se;
for( int i=0;i<n;i++){
scanf("%d",&a[i]);
se.insert(a[i]);
}
long long ans=0;
while(se.size()>1){
int x=*se.begin();
se.erase(se.begin());
int y=*se.begin();
se.erase(se.begin());
ans+=x+y;
se.insert(x+y);
}
cout<<ans<<endl;
return 0;
}
表演评分
poj2833
#include <bits/stdc++.h>
using namespace std;
const int N=20010;
int a[N];
int main(){
int n1,n2,n;
while(~scanf("%d%d%d",&n1,&n2,&n)){
if(n==0) break;
multiset<int>big;
multiset<int,greater<int> >small;
long long sum=0;
for( int i=1;i<=n;i++){
int x;
scanf("%d",&x);
sum+=x;
if(big.size()<n1){
big.insert(x);
}
else {
if(x>*big.begin()){
big.erase(big.begin());
big.insert(x);
}
}
if(small.size()<n2){
small.insert(x);
}
else {
if(x<*small.begin()){
small.erase(small.begin());
small.insert(x);
}
}
}
sum-=accumulate(big.begin(),big.end(),0ll);
sum-=accumulate(small.begin(),small.end(),0ll);
printf("%.6f\n",(double)sum/(n-n1-n2));
}
return 0;
}