博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
codeforces 722D Generating Sets 【优先队列】
阅读量:4585 次
发布时间:2019-06-09

本文共 2377 字,大约阅读时间需要 7 分钟。

You are given a set Y of n distinct positive integers y1, y2, ..., yn.

Set X of n distinct positive integers x1, x2, ..., xn is said to generate set Y if one can transform X to Y by applying some number of the following two operation to integers in X:

  1. Take any integer xi and multiply it by two, i.e. replace xi with xi.
  2. Take any integer xi, multiply it by two and add one, i.e. replace xi with xi + 1.

Note that integers in X are not required to be distinct after each operation.

Two sets of distinct integers X and Y are equal if they are equal as sets. In other words, if we write elements of the sets in the array in the increasing order, these arrays would be equal.

Note, that any set of integers (or its permutation) generates itself.

You are given a set Y and have to find a set X that generates Y and the maximum element of X is mininum possible.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 50 000) — the number of elements in Y.

The second line contains n integers y1, ..., yn (1 ≤ yi ≤ 109), that are guaranteed to be distinct.

Output

Print n integers — set of distinct integers that generate Y and the maximum element of which is minimum possible. If there are several such sets, print any of them.

Examples

Input
5 1 2 3 4 5
Output
4 5 2 3 1
Input
6 15 14 3 13 1 12
Output
12 13 14 7 3 1
Input
6 9 7 13 17 5 11
Output
4 5 2 6 3 1

 

题意:如果你有一个原数列的话你可以对任何一个数字进行操作,令这个数字乘2或者乘2后在加1。现在给你一个目标数列,让你求一个原数列,这个原数列是所有可能的原数列当中最大的一个元素最小的那种。注意原数列和目标数列都必须满足set内元素的性质(即每个元素都不相同),但是在变化的过程中不需要满足这个条件。

思路:维护一个优先队列,把集合里的数都丢进去。最大的那个数除以二,查询是否与其他数重复。不重复,则此轮结束,继续下轮最大数除二做判断;重复,则继续除二,直到找到合适的或者一直找不到,后者结束,序列即为所求。这里有个要点,是最大数除二,能停则停,换个思路,一直除到底,会占据个位置,可能让比它更大的数没办法占位置,从而算法失败,测试例子最后一个即可以验证。

代码:

#include 
#include
#include
#include
#include
#include
#define LEN 50000int n;std::set
s;void input();void work();void output();int main(){ input(); work(); output(); return 0;}void input(){ int tmp; scanf("%d", &n); for(int i=0;i
::iterator it = s.end();it--; int tmp = *it; tmp >>= 1; while (s.find(tmp)!=s.end()){ tmp >>= 1; } if (tmp){ s.erase(it); s.insert(tmp); }else{ break; } }}void output(){ std::set
::iterator it=s.begin(); printf("%d", *it); for(it++;it!=s.end();it++){ printf(" %d", *it); } puts("");}
View Code

 

转载于:https://www.cnblogs.com/jiu0821/p/10202623.html

你可能感兴趣的文章
进程和线程
查看>>
爬取校花网视频
查看>>
mysql root密码忘记最快方法
查看>>
imagemagick imagick
查看>>
DevOps - 版本控制 - Gitlab
查看>>
代码管理必备-----git使用上传码云
查看>>
静态库Lib和动态库Dll
查看>>
获取日k数据
查看>>
【LOJ】 #2132. 「NOI2015」荷马史诗
查看>>
策略模式
查看>>
DirectX11 With Windows SDK--11 混合状态
查看>>
BZOJ2982: combination Lucas模板
查看>>
UVa 10723 Cyborg Genes(LCS变种)
查看>>
Jmeter参数化
查看>>
Linux用iso镜像制作本地yum源
查看>>
在SSH项目中Struts2、Spring、Hibernate分别起到什么作用?
查看>>
网络编程协议
查看>>
5.9
查看>>
备份项目实例
查看>>
8天学通MongoDB——第二天 细说增删查改
查看>>