• CF1446C Xor Tree(01Trie)


    首先猜想一个事情,这题求树,其实是使得最多的点在一个集合,并不用考虑环的问题,在不考虑二元环的情况下,本题没有环

    举三个数的例子,如果a^b<a^c,那么ab连边,如果b^c<a^c,bc连边,那么ca不能连边,因为不等式已经约束了

    因此就要考虑如何成为连通块。对于异或的题目,很多都和字典树在一起,有很多经典套路做多了就会发现,经常是把左右当作两个独立的问题求解

    这题也可以这么思考,因为一个子树内的点一定在子树内连边,因此两个儿子集合是两个连通块,需要合并,这样势必有一个集合要为1

    因此只要递归分治考虑即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    typedef pair<pair<int,int>,int> plll;
    const int N=2e5+10;
    const int mod=1e9+7;
    int a[N];
    int tr[N*30][2];
    int idx=1;
    int sz[N*30];
    int f[N*30];
    void insert(int x){
        int p=1;
        int i;
        sz[p]++;
        for(i=30;i>=0;i--){
            int sign=x>>i&1;
            if(!tr[p][sign]){
                tr[p][sign]=++idx;
            }
            p=tr[p][sign];
            sz[p]++;
        }
    }
    void dfs(int u){
        if(u==0){
            return ;
        }
        int l=tr[u][0],r=tr[u][1];
        if(!l&&!r)
            return ;
        dfs(l);
        dfs(r);
        if(!r){
            f[u]=f[l];
        }
        else if(!l){
            f[u]=f[r];
        }
        else{
            f[u]=min(f[l]+sz[r]-1,f[r]+sz[l]-1);
        }
    }
    int main(){
        ios::sync_with_stdio(false);
        int n;
        cin>>n;
        int i;
        for(i=1;i<=n;i++){
            cin>>a[i];
            insert(a[i]);
        }
        dfs(1);
        cout<<f[1]<<endl;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    [LeetCode]Word Break
    [LeetCode]singleNumber
    [LeetCode]Palindrome
    新浪博客无法访问
    C++基础之顺序容器
    C++基础之IO类
    [LeetCode]Restore IP Addresses
    [LeetCode]Maximal Rectangle
    [LeetCode]Reverse Linked List II
    ACM 树形数组
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/14120836.html
Copyright © 2020-2023  润新知