首页 > 其他分享 >【CF888G】Xor-MST(01Trie,最小生成树)

【CF888G】Xor-MST(01Trie,最小生成树)

时间:2022-10-28 20:03:38浏览次数:58  
标签:ch Xor 子树内 CF888G 01Trie int 标记 bit 节点

看到异或最值要么是线性基要么是 01Trie。

线性基显然可以排除。

那么先把所有的 \(a_i\) 插入 01Trie 内。

然后发现对于任意两个数 \(a_i\) 和 \(a_j\):

在这里插入图片描述

你发现它们在 \(rt \sim lca\) 路径上异或出来都是 \(0\)。

不妨定义两个结束节点的 “分离节点” 为它们的 \(lca\),那么 \(a_i \operatorname{xor} a_j\) 的前 \(dep_{lca}\) 位都是 \(0\)。

对于任意两个结束节点,我们找到它们的 “分离节点” 并标记,不难发现标记点一共有 \(n-1\) 个(具体证明可以类似地参考虚树点数的证明)。

然后发现,对于任意一个标记点 ,要想让它左右子树内的结束节点联通,最优的方法就是在左右子树内各只找一个节点,然后把它们连起来。

所以 MST 中的每一条边和每一个标记点一一对应。

至于对于一个标记点找哪条边最优,可以用启发式合并,也就是枚举小的子树内的每一个结束节点,然后在大的子树内找到和它异或起来最大的。

对于每一个标记点都找一遍。

时间复杂度 \(O(n\log ^2 n)\)。

#include<bits/stdc++.h>

#define N 200010
#define ll long long
#define INF 0x7fffffff

using namespace std;

const int B=29;

int n,poww[35],a[N];
int ch[30*N][2],size[30*N],L[30*N],R[30*N];
int node;

void insert(int x,int id)
{
	int u=0;
	for(int i=B;i>=0;i--)
	{
		bool v=(x>>i)&1;
		if(!ch[u][v]) ch[u][v]=++node;
		u=ch[u][v];
		size[u]++;
		if(!L[u]) L[u]=id;
		R[u]=id;
	}
}

int query(int u,int x,int bit)
{
	if(bit<0) return 0;
	bool v=(x>>bit)&1;
	if(ch[u][v]) return query(ch[u][v],x,bit-1);
	else return query(ch[u][v^1],x,bit-1)+poww[bit];
}

ll dfs(int u,int bit)
{
	if(ch[u][0]&&ch[u][1])
	{
		bool v=(size[ch[u][1]]<size[ch[u][0]]);
		int ans=INF;
		for(int i=L[ch[u][v]];i<=R[ch[u][v]];i++)
			ans=min(ans,query(ch[u][v^1],a[i],bit-1)+poww[bit]);
		return dfs(ch[u][0],bit-1)+dfs(ch[u][1],bit-1)+ans;
	}
	if(ch[u][0]) return dfs(ch[u][0],bit-1);
	if(ch[u][1]) return dfs(ch[u][1],bit-1);
	return 0;
}

int main()
{
	poww[0]=1;
	for(int i=1;i<=B;i++)
		poww[i]=poww[i-1]<<1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
		insert(a[i],i);
	printf("%lld\n",dfs(0,B));
	return 0;
}

标签:ch,Xor,子树内,CF888G,01Trie,int,标记,bit,节点
From: https://www.cnblogs.com/ez-lcw/p/16837311.html

相关文章

  • POJ 1222(Gauss消元xor版)
    EXTENDEDLIGHTSOUTDescriptionLightsOut就是下图的游戏,给你一个5*6的矩阵. 你的目标是把灯全关上. 0表示关,1表示开.Input第一行为数据......
  • ARC139F Many Xor Optimization Problems
    题意:给定\(n,m\),求\(n\)个\([0,2^m)\)的数的最大异或和的和。瞎扯:考虑线性基,考虑消元后的,显然唯一,最大异或和为基内所有数的异或和。考虑大小为\(k\)的基方案数为......
  • 【luogu AGC034F】RNG and XOR(FWT)
    RNGandXOR题目链接:luoguAGC034F题目大意给你一个长度为2^n的数组A。一开始有一个\(0\)数,然后每次你随机给它异或上0~2^n-1中的数,随机到\(i\)的概率跟Ai+1......
  • XOR-Hashing
    link一直没听说过这个玩意,做昨天牛客的时候想到异或的结论,但是就是卡在值冲突上了。收集一些例题:CF1175FCF869ECF1622FABC250E......
  • 2020辽宁省赛 xor(前缀和DP 异或性质)
    2020辽宁省赛xor题意:​ 现在有一个长度为n的数组a。现在要将a拆分成若干个连续的子数组,要求每个连续的数组异或和都为x。请问有多少种拆分的方案。思路:​ 容易推出转......
  • 「题解」Codeforces 1572B Xor of 3
    我知道你很急,但你先别急。我急了我急了我急了。如果直接上去莽构造的话,很可能就是像我一样大分讨的后果。先特判掉全是1,或者1的个数是奇数的情况。我的做法是考虑所......
  • ABC 271 F - XOR on Grid Path(搜索 meet in the mid)
    ABC271F-XORonGridPath题意:​ 给出20*20的地图,每个点上都有一个点权,保证为正整数。请问从(1,1)走到(n,n)且路径上所有点权异或和为0的路径有多少条。思路:​......
  • XOR on Grid Path(Meet in the Middle)
    题意给定一个\(N\timesN\)的方阵,元素为\(a_{ij}\)。最初位于\((1,1)\)处,每次只能往右或往上走一格。问走到\((N,N)\)时,途径元素异或和为\(0\)的方案数为多少。题目链......
  • D1. Xor-Subsequence (easy version)
    D1.Xor-Subsequence(easyversion)https://codeforces.ml/problemset/problem/1720/D1题意给你长度为n的数组a让你找出a最长的子序列满足\(a_b_p*b_p+1<a_b_p+1......
  • CF1415D XOR-gun 题解 二分答案/贪心
    题目链接https://codeforces.com/problemset/problem/1415/D题目大意给定一个长为\(n\)的不降序列,每次操作可以任选相邻的两个数,并将这两个数替换为两个数按位异或的......