• Codeforces Round #613 (Div. 2)D(贪心,分治)


    构造两颗深度为30的字典树(根节点分别是0和1),结点只有0和1,从根节点向下DFS,贪心取答案。

     1 #define HAVE_STRUCT_TIMESPEC
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 vector<int>a;
     5 int dfs(vector<int>b,int x){
     6     if(x<0||b.size()==0)//30位都枚举完毕或当前向量中没有数字就中止
     7         return 0;
     8     vector<int>c,d;
     9     for(int i=0;i<b.size();++i){
    10         if((b[i]>>x)&1)
    11             c.push_back(b[i]);//当前位为1的数放进c
    12         else
    13             d.push_back(b[i]);//当前位为0的数放进d
    14     }
    15     if(c.size()==0)//b中所有数字当前位都为1,那么可以把题意中X的当前位构造为1(假定这一位是1),异或下来这一位就是0
    16         return dfs(d,x-1);
    17     else if(d.size()==0)//b中所有数字当前位都为0,那么可以把题意中X的当前位构造为0(假定这一位是0),异或下来这一位就是0
    18         return dfs(c,x-1);
    19     return (1<<x)+min(dfs(c,x-1),dfs(d,x-1));//b中数字当前位有0也有1,那么题意中X的当前位无论取0还是1,异或下来这一位都会是1,所以这一位异或的贡献为(1<<x),然后加上c和d两组数当中更小的贡献
    20 }
    21 int main(){
    22     ios::sync_with_stdio(false);
    23     cin.tie(NULL);
    24     cout.tie(NULL);
    25     int n;
    26     cin>>n;
    27     for(int i=1;i<=n;++i){
    28         int temp;
    29         cin>>temp;
    30         a.push_back(temp);
    31     }
    32     int ans=dfs(a,29);//二进制下从高位枚举,如果高位已经注定产生分支,那么就可以取低位贡献的最小值(低位贡献再大,合计也不会比高位某一位贡献大,所以取两个分支中较小的即可,较大的那一分支可以让它的高位异或为0,这样它低位的贡献也不会比另一分支要大。另一分支就可以贪心使得低位的贡献最小)
    33     //(可以构造一棵深度为30,分支只有0或1的字典树)
    34     cout<<ans;
    35     return 0;
    36 }
    保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
  • 相关阅读:
    如何计算java对象的大小
    目标检测复习之YOLO系列
    LeetCode173二叉搜索树迭代器
    Spring读取配置
    LeetCode165比较版本号
    haproxy状态页详解
    linux 下ab压力测试
    文服务器重建索引
    记录一次处理录音服务器故障
    在linux虚拟机上安装redis
  • 原文地址:https://www.cnblogs.com/ldudxy/p/12182241.html
Copyright © 2020-2023  润新知