题解:P6033 [NOIP 2004 提高组] 合并果子 加强版
思路
请先了解本题弱化版中的贪心思路,接下来讲如何通过本题。
发现后合并的两堆果子一定比先合并的两堆果子都要重,所以合并完了,后合并出来的那堆也一定比先合并的那堆要重。
于是发现每次往堆里面插入的值具有单调性,先插入的小。发现这个性质后,就不需要用堆来维护了,可以直接往一个队列里面插入,队列中前面的元素先插入,也就小一些。
发现值域较小,所以使用计数排序,就不需要排序的
时间复杂度为
代码
#include<bits/stdc++.h>
#define ull unsigned long long
namespace fastIO {
#define BUF_SIZE 100010
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror)
return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x*10 + ch - '0');
}
#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;
queue<ull>q2;
queue<int>q1;
ull ans;
int a,n,t[100005];
ull get(){
bool f1=q1.empty(),f2=q2.empty();
ull x;
if(f2||(!f1&&(q1.front()<=q2.front()))){
x=q1.front();
q1.pop();
}
else{
x=q2.front();
q2.pop();
}
return x;
}
int main(){
read(n);
for(int i=1;i<=n;i++){
read(a);
t[a]++;
}
for(int i=1;i<=100000;i++){
if(t[i]>0){
while(t[i]--)q1.push(i);
}
}
for(int i=1;i<n;i++){
ull x=get()+get();
ans+=x;
q2.push(x);
}
printf("%llu",ans);
return 0;
}