題意:
給你含有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;
}