• 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:

    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 <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
  • 相关阅读:
    福大软工 · BETA 版冲刺前准备(团队)
    福大软工 · 第十一次作业
    Alpha 冲刺 (9/10)
    Alpha 冲刺 (8/10)
    Alpha 冲刺 (7/10)
    Alpha 冲刺 (6/10)
    Alpha 冲刺 (5/10)
    Alpha 冲刺 (4/10)
    福大软工1816 · 团队现场编程实战(抽奖系统)
    阿里八八β阶段Scrum(5/5)
  • 原文地址:https://www.cnblogs.com/jiu0821/p/10202623.html
Copyright © 2020-2023  润新知