洛谷 P1090 [NOIP 2004 提高组] 合并果子
每次把最小两个堆合并即可。
题解都在用小根堆,但由于本菜鸡忘了小根堆stl创建方法,以及不想手写小根堆,因而转用multiset,也能过,复杂度大概是O(nlogn)
#include<iostream>
#include<set>
using namespace std;
int main(){
multiset<int> s; // 使用multiset允许重复元素
int N, ans = 0;
cin >> N;
while(N--){
int x;
cin >> x;
s.insert(x);
}
while(s.size() > 1){
auto a = s.begin();
int sum = *a + *(++a);
s.erase(s.begin());
s.erase(s.begin());
ans += sum;
s.insert(sum);
}
cout << ans;
return 0;
}
补充手写的小根堆。。。这次码风有点问题,偷懒了。。
AcCode:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int heap[10010], idx = 1;
void up(int index){
if(heap[index] >= heap[index / 2] || index == 0) return ;
swap(heap[index], heap[index / 2]);
up(index / 2);
}
void insert(int v){
heap[idx] = v;
up(idx++);
}
void down(int index){
int left = index * 2;
int right = left + 1;
if(left >= idx) return ;
if(right < idx){
if(heap[right] > heap[left] && heap[index] > heap[left]) swap(heap[left], heap[index]), down(left);
else if(heap[right] < heap[index]) swap(heap[right], heap[index]), down(right);
}else if(heap[index] > heap[left]) swap(heap[left], heap[index]), down(left);
}
void pop(){
heap[1] = heap[--idx];
down(1);
}
int top(){
return heap[1];
}
int main(){
int N, ans = 0;
cin >> N;
int m = N;
while(N--){
int x;
cin >> x;
insert(x);
}
for(int i = 1; i < m; i++){
int a = top();
pop();
int b = top();
pop();
ans += a + b;
insert(a + b);
}
cout << ans;
return 0;
}