Title

CF1446C Xor Tree 题解

解题思路

与其考虑删除哪些点,不如考虑保留哪些点。考虑到和异或有关,那么我们可以把这些数倒序插入 trie 树中,然后我们就可以在 trie 树上跑一个简单的 dp:

  • 若当前节点为叶子节点,那么保留,返回 \(1\)
  • 若当前节点在链上,那么直接继承儿子节点;
  • 若当前节点有两个儿子,那么更新为较大儿子加 \(1\)

AC 代码

#include<stdio.h>
#include<stdlib.h>
#include <vector>
#define N 6000005
int n,a[N],cnt;
int trie[N][2];
inline void Insert(int x){
    std::vector<int> lin;
    lin.push_back(0);
    while(x){
        lin.push_back(x&1);
        x>>=1;
    }while(lin.size()<35)
        lin.push_back(0);
    int now=0;
    for(register int i=lin.size()-1;i;--i){
        int next=lin[i];
        if(!trie[now][next])
            trie[now][next]=++cnt;
        now=trie[now][next];
    }
}
inline int dfs(int u){
    if(trie[u][0]&&trie[u][1])
        return std::max(
            dfs(trie[u][0]),
            dfs(trie[u][1])
        )+1;
    if(!trie[u][0]&&!trie[u][1])
        return 1;
    if(!trie[u][0]) return dfs(trie[u][1]);
    if(!trie[u][1]) return dfs(trie[u][0]); 
}
signed main(){
    scanf("%d",&n);
    for(register int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    for(register int i=1;i<=n;++i)
        Insert(a[i]);
    printf("%d",n-dfs(0));
}
posted @ 2024-02-07 10:03  UncleSam_Died  阅读(41)  评论(0)    收藏  举报