【CodeForces - 722D 】Generating Sets(貪心+優先隊列)

題意:

給你含有N個不同的正整數的集合,y1,y2...yn 。
他們是由N個不同的正整數的集合x1,x2...xn轉換而來的。
每次改變只能選擇以下幾種操作:
1.將xi乘以2
2.將xi乘以2後加一
可以改變無數次。
問最大值最小的x序列是什麼樣的。
有多個答案的話,輸出任意一個即可。

Input

輸入n,表示有n個數字。(1 <= n <= 50,000) 
接下來n個不同的數表示y1,y2..yn (1 <= yi <= 1e9)

Output

輸出n個不同的數。
它們能通過1或2操作轉化爲Y集合,且其中的最大值最小。

思路:

根據操作,可以發現數字的變化是一顆二叉樹,貪心的思路是先將最大的元素減小但是不減小到最小。所以將所有元素放入優先隊列,取出最大的元素,找到他能減小到的第一個沒有出現的數,然後將這個數放回。重複操作,直到不能操作爲止。

ac代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<unordered_map>
#include<set>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=100000;
int a[maxn],n;
priority_queue<int> q;
unordered_map<int,int> mp;
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        q.push(a[i]);
        mp[a[i]]++;
    }
    int fl=1;
    while(fl){
        int tmp=q.top();q.pop();
        int ans=tmp;
        while(tmp>0&&mp[tmp]){
            tmp/=2;
        }
        if(tmp>0&&!mp[tmp]){
            q.push(tmp);
            mp[ans]--;
            mp[tmp]++;
        }
        else{
            q.push(ans);
            break;
        }
    }
    while(q.size()){
        int ans=q.top();q.pop();
        printf("%d%c",ans,q.size()?' ':'\n');
    }

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章