CodeForces-884D:Boxes And Balls(合并石子)
Ivan has n different boxes. The first of them contains some balls of n different colors.
Ivan wants to play a strange game. He wants to distribute the balls into boxes in such a way that for every i (1 ≤ i ≤ n) i-th box will contain all balls with color i.
In order to do this, Ivan will make some turns. Each turn he does the following:
- Ivan chooses any non-empty box and takes all balls from this box;
- Then Ivan chooses any k empty boxes (the box from the first step becomes empty, and Ivan is allowed to choose it), separates the balls he took on the previous step into k non-empty groups and puts each group into one of the boxes. He should put each group into a separate box. He can choose either k = 2 or k = 3.
The penalty of the turn is the number of balls Ivan takes from the box during the first step of the turn. And penalty of the game is the total penalty of turns made by Ivan until he distributes all balls to corresponding boxes.
Help Ivan to determine the minimum possible penalty of the game!
Input
The first line contains one integer number n (1 ≤ n ≤ 200000) — the number of boxes and colors.
The second line contains n integer numbers a1, a2, ..., an (1 ≤ ai ≤ 109), where aiis the number of balls with color i.
Output
Print one number — the minimum possible penalty of the game.
Example
3
1 2 3
6
4
2 3 4 5
19
题意:一共N小堆石子,每堆有自己的重量,开始都合在一大堆。现在问这样可以让他们分成N小堆。具体的,每次可以选择一个大的堆(其重量为代价),分为2或者3个堆。
思路:逆向考虑就是石子合并:若干堆石子,都有自己的重量,每一次可以选2或者3堆合成一堆,每次的代价为所选石子重量和。
对于此类题型,我们考虑到合并的次数是一定的,所以我们希望重量轻的其“凑次数”,即是把轻的优先合并,然后把合并的结果再拿去排序,等待下一次合并。
对于此题:显然能分为3个堆的情况优于分为2个堆(次数少一些),其他的与普通的合并石子无差。 然后就是考虑到每次减少2堆,最后要留1堆,所以对于偶数堆还应该插入“0”。
#include<queue> #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; #define ll long long const int maxn=200010; priority_queue<ll,vector<ll>,greater<ll> >q; ll a[maxn]; int main() { int N,i,j; ll ans=0,tmp; scanf("%d",&N); for(i=1;i<=N;i++) { scanf("%lld",&a[i]); q.push(a[i]); } if(N==1) { printf("0\n"); return 0; } if(N%2==0) q.push(0); while(q.size()>3){ tmp=q.top(); q.pop(); tmp+=q.top(); q.pop(); tmp+=q.top(); q.pop(); ans+=tmp; q.push(tmp); } while(!q.empty()){ ans+=q.top(); q.pop(); } printf("%lld\n",ans); return 0; }