codeforces 722D Generating Sets 【優先佇列】
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
Note, that any set of integers (or its permutation) generates itself.
You are given a set Y and have to find a set X
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
Input5Output
1 2 3 4 5
4 5 2 3 1Input
6Output
15 14 3 13 1 12
12 13 14 7 3 1Input
6Output
9 7 13 17 5 11
4 5 2 6 3 1
題意:如果你有一個原數列的話你可以對任何一個數字進行操作,令這個數字乘2或者乘2後在加1。現在給你一個目標數列,讓你求一個原數列,這個原數列是所有可能的原數列當中最大的一個元素最小的那種。注意原數列和目標數列都必須滿足set內元素的性質(即每個元素都不相同),但是在變化的過程中不需要滿足這個條件。
思路:維護一個優先佇列,把集合裡的數都丟進去。最大的那個數除以二,查詢是否與其他數重複。不重複,則此輪結束,繼續下輪最大數除二做判斷;重複,則繼續除二,直到找到合適的或者一直找不到,後者結束,序列即為所求。這裡有個要點,是最大數除二,能停則停,換個思路,一直除到底,會佔據個位置,可能讓比它更大的數沒辦法佔位置,從而演算法失敗,測試例子最後一個即可以驗證。
程式碼:
#include <iostream> #include <cstdio> #include <vector> #include <queue> #include <algorithm> #include <set> #define LEN 50000 int n; std::set<int> 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<n;i++){ scanf("%d", &tmp); s.insert(tmp); } } void work(){ while(true){ std::set<int>::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<int>::iterator it=s.begin(); printf("%d", *it); for(it++;it!=s.end();it++){ printf(" %d", *it); } puts(""); }View Code