• Codeforces 976E/925C (01Trie树)


    传送门


    题面:

    C. Big Secret
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Vitya has learned that the answer for The Ultimate Question of Life, the Universe, and Everything is not the integer 54 42, but an increasing integer sequence a1,,an

    . In order to not reveal the secret earlier than needed, Vitya encrypted the answer and obtained the sequence b1,,bn

    using the following rules:

    • b1=a1
    ; bi=aiai1 for all i from 2 to n, where xy is the bitwise XOR of x and y
    • .

    It is easy to see that the original sequence can be obtained using the rule ai=b1bi

    .

    However, some time later Vitya discovered that the integers bi

    in the cypher got shuffled, and it can happen that when decrypted using the rule mentioned above, it can produce a sequence that is not increasing. In order to save his reputation in the scientific community, Vasya decided to find some permutation of integers bi so that the sequence ai=b1bi

    is strictly increasing. Help him find such a permutation or determine that it is impossible.

    Input

    The first line contains a single integer n

    (1n105

    ).

    The second line contains n

    integers b1,,bn (1bi<260

    ).

    Output

    If there are no valid permutations, print a single line containing "No".

    Otherwise in the first line print the word "Yes", and in the second line print integers b1,,bn

     — a valid permutation of integers bi. The unordered multisets {b1,,bn} and {b1,,bn} should be equal, i. e. for each integer x the number of occurrences of x in the first multiset should be equal to the number of occurrences of x in the second multiset. Apart from this, the sequence ai=b1bi

    should be strictly increasing.

    If there are multiple answers, print any of them.

    Examples
    Input
    Copy
    3
    1 2 3
    
    Output
    Copy
    No
    
    Input
    Copy
    6
    4 7 7 12 31 61
    
    Output
    Copy
    Yes
    4 12 7 31 7 61 
    
    Note

    In the first example no permutation is valid.

    In the second example the given answer lead to the sequence a1=4

    , a2=8, a3=15, a4=16, a5=23, a6=42

    .


    Codeforces (c) Copyright 2010-2018 Mike Mirzay

        题目描述:给你一个n个数的数列,问你是否可以使数列中的某些元素调换,使得新数列满足,Ai=(B1 xor B2 xor...Bi)严格单调递增。

        题目分析:因为这道题所要我们求的是异或和递增,我们不妨从最终的异或和开始倒推,每次都让他递减,那我们就可以贪心的选择减少得最少的。

        而因为这题我们维护的是异或和,因此我们可以通过Trie树进行维护。

        具体的做法是,我们从最高位往地位去枚举,如果当前的位数为s=1,则无论x取0还是1都会使得最终的s变小,而我们希望减少量不至于太大,因此我们优先考虑x=0的情况,如果找不到x=1,再考虑x=0的情况。

        如果当前的位数s=0,则如果我们取x=1,会使得s在这一位上变大,这种操作只在高位存在s从1变成0的情况下才能够成立,如果成立,则从减少变化量的角度来讲,则优先得从x=0来考虑,x=1找不到再找x=0的。

        整体是的做法就类似与在Trie树上去做一趟数位dp,不断寻找符合条件的数,最后存储即可。

        具体可以看一下代码

    #include <bits/stdc++.h>
    #define maxn 6000005
    using namespace std;
    typedef long long ll;
    int n;
    struct Trie{
        int trie[maxn][2];//trie树
        int cnt[maxn];//每个节点所经过的数量
        int root=0;//根
        ll val[maxn];//中断点的坐标
        ll xorsum=0;//异或和
        ll ans[maxn/10];//答案
        int C=0;
        int newroot(){//新开结点
            trie[C][0]=trie[C][1]=-1;
            cnt[C]=0;
            return C++;
        }
        void Insert(ll x){//trie树的插入
            ll p=root;
            for(int i=60;i>=0;i--){
                ll id=(x>>i)&1;
                if(trie[p][id]==-1) trie[p][id]=newroot();
                p=trie[p][id];
                cnt[p]++;
            }
            val[p]=x;
        }
        bool check(ll xorsum,ll &res,int index,bool limit,int dep){//limit代表前一位是否有从1变为0的情况,dep代表深度
            if(index!=root&&(cnt[index]==0||index==-1)) return false;
            if(dep==-1){//深度为-1证明完全满足条件,则最终结果为val[index]
                res=val[index];
                cnt[index]--;
                return true;
            }
            int id=(xorsum>>dep)&1;//获取当前异或和的深度的位数
            if(id==0){//判断当前位为0
                bool ret=(check(xorsum,res,trie[index][0],limit,dep-1))||
                (!limit&&check(xorsum,res,trie[index][1],limit,dep-1));
                if(ret==0) return false;
                cnt[index]--;
                return true;
            }
            else{//判断当前位为1的情况
                bool ret=(check(xorsum,res,trie[index][0],limit,dep-1))||
                (check(xorsum,res,trie[index][1],false,dep-1));
                if(ret==0) return false;
                cnt[index]--;
                return true;
            }
        }
        void solve(){
            for(int i=n-1;i>=0;i--){
                ll res;
                bool ret=check(xorsum,res,root,true,60);
                if(ret==0){
                    puts("No");
                    return;
                }
                ans[i]=res;
                assert(xorsum>(xorsum^res));
                xorsum^=res;
            }
            puts("Yes");
            for(int i=0;i<n;i++){
                cout<<ans[i]<<" ";
            }
            puts("");
        }
    }Tree;
    int main()
    {
        scanf("%d",&n);
        Tree.root=Tree.newroot();
        for(int i=0;i<n;i++){
            ll x;
            scanf("%I64d",&x);
            Tree.Insert(x);
            Tree.xorsum^=x;
        }
        Tree.solve();
    }
    

  • 相关阅读:
    关于数据库的基础知识
    Oracle数据库的上机作业
    PHP表单处理
    EasyUI DataGrid结合ThinkPHP实现增删改查操作———初学者
    Redis crackit
    nodeppt安装后,phantomjs不能运行了 Bad argument
    redis命令
    eclipse编辑web.xml很慢
    客制化jasperreport导出html的过程
    dynamicreport, JFreeChart
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007295.html
Copyright © 2020-2023  润新知