【CodeForces - 722D 】Generating Sets(贪心+优先队列)

mac2024-10-12  70

题意:

给你含有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; }

 

最新回复(0)