• CF1446C Xor Tree


    对于每个点(i),找到(j eq i)(a_j xor a_i)最小,连边((i,j))

    如果连边之后形成一棵树,那么称({a_i})为合法的。

    给出({a_i}),求至少删掉多少个点才合法。

    (nle 2*10^5)

    (a_i)互不相同


    这题搞得可真是惊心动魄……搞了三个做法,最后一个终于对了……

    干了1.5h。

    假设连有向边(i o j),那么建出的图是个基环树森林。并且每棵基环树的环长为(2)

    如果合法,那么必须满足:只存在一对((i,j)),满足对于各自而言,(a_i xor a_j)都是最小的。

    自然这也会是全局最小异或值。之前有个结论,对于一堆朴素的({a_i}),其中最小的(a_i xor a_j)一定是排序之后相邻的。

    于是最终如何保留树才合法呢?建出Trie,发现长这样:

    这样dfs找一下就好了。


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 200005
    #define INF (1<<30)
    int n;
    int a[N];
    struct Node{
    	Node *c[2];
    	int siz;
    } d[N*40],*rt;
    int cnt;
    void insert(int x,int c=1){
    	Node *t=rt;
    	for (int i=29;i>=0;--i){
    		t->siz+=c;
    		if (!t->c[x>>i&1]){
    			t->c[x>>i&1]=&d[++cnt];
    			d[cnt]={NULL,NULL};
    		}
    		t=t->c[x>>i&1];
    	}
    	t->siz+=c;
    }
    int ans;
    void dfs(Node *t,int s){
    	if (t->c[0] && t->c[0]->siz==1 && t->c[1] && t->c[1]->siz==1)
    		ans=max(ans,2+s);
    	if (t->c[0]) dfs(t->c[0],s+(t->c[1]?1:0));
    	if (t->c[1]) dfs(t->c[1],s+(t->c[0]?1:0));
    }
    int main(){
    //	freopen("in.txt","r",stdin);
    	rt=&d[cnt=1];
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i){
    		scanf("%d",&a[i]);
    		insert(a[i]);
    	}
    	ans=2;
    	dfs(rt,0);
    	printf("%d
    ",n-ans);
    	return 0;
    }
    
  • 相关阅读:
    4-MSP430定时器_定时器中断
    关于STM32的外部引脚中断的问题
    关于stm32的正交解码
    红外接收控制灯亮灭
    mack pro常用快捷键
    liunx操作系统安装<一>
    支付宝架构师:从工程师到架构师的成长之路
    maven之setting.xml的配置详解
    分布式之《保证分布式系统数据一致性的6种解决方案》
    Eclipse中jsp、js文件编辑时,卡死现象解决汇总
  • 原文地址:https://www.cnblogs.com/jz-597/p/13986661.html
Copyright © 2020-2023  润新知