zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Attributes in C#
    asp.net C# 时间格式大全
    UVA 10518 How Many Calls?
    UVA 10303 How Many Trees?
    UVA 991 Safe Salutations
    UVA 10862 Connect the Cable Wires
    UVA 10417 Gift Exchanging
    UVA 10229 Modular Fibonacci
    UVA 10079 Pizza Cutting
    UVA 10334 Ray Through Glasses
  • 原文地址:https://www.cnblogs.com/jz-597/p/13986661.html
Copyright © 2011-2022 走看看