1. 程式人生 > >合併果子(佇列和優先佇列)

合併果子(佇列和優先佇列)

有兩種方法 一種是佇列 一種是優先佇列(priority_queue)
這兩種方法的區別是佇列定義時沒有自動排序 所以只能在輸入的時候按順序才能輸出正解(所以佇列的方法不被認為是正解) 下面是程式碼 比較簡便:

#include<bits/stdc++.h>
using namespace std;
queue<int>q;
int main() {
  int n,x;
  cin>>n;
  for(int i=0;i<n;i++) {
    cin>>x;
    q.push(x);
  }
  int ans=0;
  for
(int i=1;i<n;i++) { ans+=q.front(); q.pop(); ans+=q.front(); q.pop(); q.push(ans); } cout<<ans; }

但是如果用了優先佇列的話,剛開始就給你的是一個大根堆(從大到小排序)如果想讓這個佇列等價於一個小根堆,就可以入隊的時候加一個負號,eg:(-1 -2 -9)這樣就會按照絕對值從小到大排列 於是計數的時候用ans減去q.top()就ok了 然後這時候需要一個tmp來記錄下來合併果子的和,然後將合併後的果子放到隊尾 程式碼實現:

#include
<bits/stdc++.h>
using namespace std; priority_queue<int>q; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n,x; cin>>n; for(int i=0;i<n;i++) { cin>>x; q.push(-x); } int ans=0,tmp; while(q.size()>1) { tmp=q.top(); ans-=q.top
(); q.pop(); tmp+=q.top(); ans-=q.top(); q.pop(); q.push(tmp); } cout<<ans; }

前幾行是關閉同步,可以加速。 while的地方可以改寫成for迴圈的形式:

#include<bits/stdc++.h>
using namespace std;
priority_queue<int>q;
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,x;
  cin>>n;
  for(int i=0;i<n;i++) {
    cin>>x;
    q.push(-x);
  }
  int ans=0,tmp;
  for(int i=1;i<n;i++){
    tmp=q.top();
    ans-=q.top();
    q.pop();
    tmp+=q.top();
    ans-=q.top();
    q.pop();
    q.push(tmp);
  }
  cout<<ans;
}

就是這樣