首页 > 其他分享 >字典树

字典树

时间:2023-01-15 16:44:19浏览次数:40  
标签:dist int 异或 LCA Root xorSum 字典

题目链接

核心思路

题目是要我们找到两个点,使得这两个点的路径上的边权异或值最大。

首先我们先别管这个树是个什么样的结构,我们需要清楚的就是看可以做个什么样的转换,使得挖掘到我们想要的性质。

我们令LCA代表的是X和Y的公共祖先,Root代表的是整棵树的根节点,Sum(X,Y)表示的是X到Y路径上面的边权异或和。

于是我们可以做以下推导:

\(Sum(X,Y)\)

\(=Sum(X,LCA)xorSum(Y,LCA)\)

\(=Sum(X,LCA)xorSum(Y,LCA)xorSum(LCA,Root)xorSum(LCA,Root)\)

\(=Sum(X,LCA)xorSum(LCA,Root)xorSum(Y,LCA)xorSum(LCA,Root)\)

\(=Sum(X,Root)xorSum(Y,Root)\)

所以我们只需要求出来根节点到每一个节点的异或和,然后找出一对使其异或值最小。

这里我们可以通过dfs求出来,假设dist数组是我们求出来的。

接下来再怎么做呢,这个就转换到了我们熟悉的问题,也就是使其两个数的异或和最大。

我们可以把这些数都插入到异或字典树里面去,然后一个一个的找。

比如我们要找dist[3]与他匹配的最大异或和。

那么我们可以从高位到低位一位一位的找,如果这一位是1,那么我们就去0这个分枝。如果这一位是0,那么我们就去1这个分枝。

其实就和这个题目是一样的

所以我们需要多总结我们做过的一些模型,有时候直接套板子就好了。

// Problem: A. Make it Beautiful
// Contest: Codeforces - Educational Codeforces Round 141 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1783/problem/0
// Memory Limit: 512 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e7 + 10;
int e[N], h[N], ne[N], idx, w[N];
int tr[N][2];
int cnt;
int dist[N];
int en[N];
void add(int a, int b, int c)
{
	w[idx] = c;
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx++;

}
//求dist数组
void dfs(int u, int fa)
{
	for (int i = h[u];~i;i = ne[i])
	{
		int j = e[i];
		int val = w[i];
		if (j == fa)
			continue;
		dist[j] = (val ^= dist[u]);//j的父节点就是u
		dfs(j, u);
	}
}
void insert(int x)
{
	int p = 0;
	for (int i = 31;i >= 0;i--)
	{
		int k = ((x >> i) & 1);
		if (!tr[p][k])
			tr[p][k] = ++idx;
		p = tr[p][k];
	}
	en[p] = 1;
}
int find(int num)
{
	int p = 0;
	int sum = 0;
	for (int i = 31;i >= 0;i--)
	{
		int k = ((num >> i) & 1);
		if (tr[p][k ^ 1])
		{
			sum += (1 << i);
			p = tr[p][k ^ 1];
		}
		else
			p = tr[p][k];
	}
	return sum;
}



int main()
{
	memset(h, -1, sizeof h);
	int n;
	cin >> n;
	for (int i = 1;i <= n - 1;i++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);
		add(b, a, c);
	}
	dist[1] = 0;
	dfs(1, -1);
	int sum = 0;
	/*for(int i=1;i<=n;i++)
		cout<<dist[i]<<" ";
		cout<<endl;*/
/*	dist[1]=0;
	dist[2]=3;
	dist[3]=5;
	dist[4]=7;*/
	for (int i = 1;i <= n;i++)
		insert(dist[i]);
	for (int i = 1;i <= n;i++)
	{
		sum = max(sum, find(dist[i]));
	}
	cout << sum << endl;
	return 0;


}

标签:dist,int,异或,LCA,Root,xorSum,字典
From: https://www.cnblogs.com/xyh-hnust666/p/17053708.html

相关文章

  • Python之字典添加元素
    本文使用代码book_dict={"price":500,"bookName":"Python设计","weight":"250g"} 第一种方式:使用[]book_dict["owner"]="tyson" 说明:中括......
  • Python字典和集合初窥
    (Python进阶10-字典与集合)1字典字典和列表类似,同样是可变序列,不过与列表不同,字典是无序的。字典的主要特征:1.1字典的创建和删除字典的每个元素都包含“键”和“......
  • 可持久化字典树
    在介绍可持久化字典树之前,我们先要说一下01字典树。01字典树的一个功能是:向当前集合中插入一个正整数。查询当前集合中异或上x后最大的那个数。接下来介绍一下这两个......
  • 字典树(Trie)
    字典树Trie树,即字典树,是一种树形结构。典型应用是用于统计和排序大量的字符串前缀来减少查询时间,最大限度地减少无谓的字符串比较。Trie树的核心思想是空间换时间。利......
  • E. Beautiful Subarrays(01字典树)
    Problem-E-Codeforces题意:给一个长度为n的数组a,问有多少个连续的子数组的异或和大于等于k思路:01字典树建立前缀异或和数组,题目变为有多少个$a_iˆa_j(1......
  • Trie树 (字典树)
    什么是trie树trie树是一种用来查找字符串的树形结构,利用字符串公共信息把多个字符串存储成一棵树,节约内存,加快检索速度这是一棵字典树trie树的性质1.根节点为空......
  • python列表里的字典元素去重
    去重:fromfunctoolsimportreduce#导入排序模块#列表里的字典元素去重复deflist_dict_duplicate_removal(data_list):run_function=lambdax,y:xifyi......
  • 数据结构——字典树
    NO.1定义字典树又称单词查找树,\(Trie\)树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文......
  • jeecgBoot对象字典解析
    接口:interface CommonService声明:publicJSONObjectconvertObjDict(Objectobj,booleanisIgnore,String...columns);实现类:classCommonServiceImplimplements......
  • 元组和字典
    一.元组1.与列表类似,区别在于:①元组用小括号()定义,②元组的元素不能修改2.操作:①交换变量的值        ②元组的方法  .count()和.index()     ......