您的位置:首页 > 其它

Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) D. Generating Sets __ dfs+优先队列+贪心

2016-10-03 22:11 513 查看
D. Generating Sets

time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

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:

Take any integer xi and
multiply it by two, i.e. replace xi with 2·xi.

Take any integer xi,
multiply it by two and add one, i.e. replace xi with 2·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


Source

Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)

My Solution

dfs+优先队列+贪心

向把数读入到priority_queue, 同时用 map<int, bool> mp来标记这些数字,出现过。

然后每次贪心的取最大的值,u = pq.top(), mp[u] = false; 然后dfs的向下推可行的一步,比如 13 到 6 如果可以就标记并返回,否者继续向下找。

如果最大值已经不能向下推了,则pq里维护着的元素就是答案了。

此外,这个方法对于 n == 1时要特殊处理, 不然n == 1的时候 一直mp[1] = false,然后dfs(1),这样每次flag都被标记跳不出循环了

总复杂度 O(nlognlogn)

#include <iostream>
#include <cstdio>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn = 5e5 + 8;

int v;
map<int, bool> mp;
priority_queue<int> pq;
bool flag;
/*//一次性放好不大行,会出问题,比如样例3,
//还是用pq来维护每次把最大的向下推一次,
void dfs(LL x, int i)
{
if(x == 1){
if(mp[x] == false){
mp[x] = true;
v[i] = x;
flag = true;
}
return;
}
if(x & 1){
dfs((x - 1) / 2, i);
if(!flag){
if(mp[x] == false){
mp[x] = true;
v[i] = x;
flag = true;
}
}
return;
}
else{
dfs(x / 2, i);
if(!flag){
if(mp[x] == false){
mp[x] = true;
v[i] = x;
flag = true;
}
return;
}
}
//......
if(!flag){
mp[x] = true;
v[i] = x;
}

}
*/
//用priority_queue 来维护, 每次取最大值, 向下推一步,
//然后重新取最大值, 这样一步一步的往下推
//直到最大值不能向下推,得到答案, 因为要求最大值尽可能小, 所以对其它值不做要求
//总的复杂度依然是 O(nlogn);
inline void dfs(int x)
{
if(x == 1){
if(mp[x] == false){
mp[x] = true;
v = x;
flag = true;
}
return;
}
if(x & 1){
if(mp[(x - 1) / 2] == false){
mp[(x - 1) / 2] = true;
v = (x - 1) / 2;
flag = true;
return;
}
dfs((x - 1) / 2);
}
else{
if(mp[x / 2] == false){
mp[x / 2] = true;
v = x / 2;
flag = true;
return;
}
dfs(x / 2);
}
//......

}

int main()
{
#ifdef LOCAL
freopen("d.txt", "r", stdin);
//freopen("d.out", "w", stdout);
int T = 3;
while(T--){
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);

int n, u;
cin >> n;
for(int i = 0; i < n; i++){
cin >> v;
mp[v] = true;
pq.push(v);
}
if(n == 1){ cout << 1 << endl; return 0;}  //!

while(true){
u = pq.top();
pq.pop();
mp[u] = false;
flag = false;
//cout << v[i] << " ";
dfs(u);
if(!flag) {pq.push(u); break;}
pq.push(v);
//cout << v[i]<<endl;
}

cout << pq.top(); pq.pop();
while(!pq.empty()){
cout << " " << pq.top();
pq.pop();
}
cout << endl;

#ifdef LOCAL
mp.clear();
cout << endl;
}
#endif // LOCAL
return 0;
}


  Thank you!

                                                                                                           
                                   ------from ProLights 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐