hdu4757 可持续字典树

Tree

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 2058    Accepted Submission(s): 599

Problem Description

Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will give One an tree and every node in this tree has a value. Then, Zero will ask One a series of queries. Each query contains three parameters: x, y, z which mean that he want to know the maximum value produced by z xor each value on the path from node x to node y (include node x, node y). Unfortunately, One has no idea in this question. So he need you to solve it.

Input

There are several test cases and the cases end with EOF. For each case:

The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^5), which are the amount of tree’s nodes and queries, respectively.

The second line contains n integers a[1..n] and a[i](0<=a[i]<2^{16}) is the value on the ith node.

The next n–1 lines contains two integers u v, which means there is an connection between u and v.

The next m lines contains three integers x y z, which are the parameters of Zero’s query.

Output

For each query, output the answer.

Sample Input

3 2

1 2 2

1 2

2 3

1 3 1

2 3 2

Sample Output

3

0

先放模仿代码,我是先6191不会做然后学了一下。。

http://blog.csdn.net/acterminate/article/details/77750707

我觉得这个可持续字典树的写法有点像AC自动机的意思,他没有的son就相当于失配指针,从而跳到前面有的地方

先用0作为一个源节点,然后用LCA搞一下分两步,分别求LCA(u,v)的父节点到u和到v的值,哪个大取哪个就OK了。

#include<cstdio>#include<cstring>#include<algorithm>const int N=100008;int a[N],head[N],tot,index,cont,n,m;int root[N],tree[N*35][2],son[N*35][2];int fa[N],depth[N],up[N][18],pt[N];struct node{   int next,to;}e[N<<1];void add(int u,int v){   e[tot].next=head[u];e[tot].to=v;head[u]=tot++;   e[tot].next=head[v];e[tot].to=u;head[v]=tot++;}void build(int last,int cur,int num,int pos){   if(pos<0) return;   int temp=!!(num&(1<<pos));   tree[cur][temp]=tree[last][temp]+1;   son[cur][temp^1]=son[last][temp^1];   tree[cur][temp^1]=tree[last][temp^1];   build(son[last][temp],son[cur][temp]=++cont,num,pos-1);//这里可以看到每一个数字都建立了31个节点,其实只要17个就够了根据题意}void dfs(int u){   pt[u]=++index;//记录一下每个节点在树中的位置   build(root[pt[fa[u]]],root[pt[u]]=++cont,a[u],31);   for(int i=head[u];~i;i=e[i].next){    int v=e[i].to;    if(fa[u]==v) continue;    fa[v]=u;    depth[v]=depth[u]+1;    dfs(v);   }}void doit(){    for(int i=1;i<=n;++i) up[i][0]=fa[i];    for(int j=1;j<=16;++j) for(int i=1;i<=n;++i) up[i][j]=up[up[i][j-1]][j-1];}int lca(int x,int y){    if(depth[x]<depth[y]) std::swap(x,y);    int dt=depth[x]-depth[y];    for(int i=0;i<=16;++i) if(dt&(1<<i)) x=up[x][i];    if(x==y) return x;    for(int i=16;i>=0;--i) if(up[x][i]!=up[y][i]) x=up[x][i],y=up[y][i];    return up[x][0];}int query(int last,int cur,int num,int sum,int pos){   if(pos<0) return sum;   int temp=!!(num&(1<<pos));   if(tree[cur][temp^1]-tree[last][temp^1]>0) return query(son[last][temp^1],son[cur][temp^1],num,sum|(1<<pos),pos-1);   else return query(son[last][temp],son[cur][temp],num,sum,pos-1);}int main(){   int x,y,z;   while(scanf("%d%d",&n,&m)!=EOF){    memset(head,-1,sizeof(head));    index=tot=cont=0;    for(int i=1;i<=n;++i) scanf("%d",&a[i]);    for(int i=1;i<n;++i) {scanf("%d%d",&x,&y);add(x,y);}    dfs(1);    doit();    while(m--){        scanf("%d%d%d",&x,&y,&z);        int ct=lca(x,y);        int mx=query(root[pt[fa[ct]]],root[pt[x]],z,0,31);        mx=std::max(query(root[pt[fa[ct]]],root[pt[y]],z,0,31),mx);        printf("%d\n",mx);    }   }}
时间: 2024-08-12 22:16:01

hdu4757 可持续字典树的相关文章

Hdu-4757 Tree(可持久化字典树+lca)

题目链接:点这 我的github地址:点这 Problem Description Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will giv

9-11-Trie树/字典树/前缀树-查找-第9章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第9章  查找 - Trie树/字典树/前缀树(键树) ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c        相关测试数据

【数据结构】字典树/Trie树/前缀树 - 字符串的统计、排序和保存

字典树 描述 字典树,又称单词查找树.Trie树.前缀树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计.排序和保存大量的字符串(但不仅限于字符串). 常见操作有插入和查找,删除操作少见. 性质 根节点不包含字符 除根节点外每一个节点都只包含一个字符 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串 每个节点的所有子节点包含的字符都不相同 优点 利用字符串的公共前缀来减少查询时间 最大限度地减少无谓的字符串比较 查询效率比哈希树高 自带字典序排序 直接判断重复,或者记

hdu 1251 统计难题(字典树)

Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input 输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串. 注意:本题只有一组测试数据,处理到文件结束. Output 对于每个提

51nod round3# 序列分解(折半枚举+字典树)

小刀和大刀是双胞胎兄弟.今天他们玩一个有意思的游戏. 大刀给小刀准备了一个长度为n的整数序列.小刀试着把这个序列分解成两个长度为n/2的子序列. 这两个子序列必须满足以下两个条件: 1.他们不能相互重叠. 2.他们要完全一样. 如果小刀可以分解成功,大刀会给小刀一些糖果. 然而这个问题对于小刀来说太难了.他想请你来帮忙. Input 第一行给出一个T,表示T组数据.(1<=T<=5) 接下来每一组数据,输入共2行. 第一行包含一个整数n (2<=n<=40且为偶数). 第二行给出n

白话算法与数据结构之【字典树】

1. 什么是trie树 1.Trie树 (特例结构树) Trie树,又称单词查找树.字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高.      Trie的核心思想是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. Trie树也有它的缺点,Trie树的内存消耗非常大.当然,或许用左儿子

[算法系列之二十]字典树(Trie)

一 概述 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 二 优点 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高. 三 性质 (1)根节点不包含字符,除根节点外每一个节点都只包含一个字符: (2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串: (3)每个节点的所有子节点包含的字符都不相同. 单词列表为"apps&

poj 3764 The xor-longest Path(字典树)

题目链接:poj 3764 The xor-longest Path 题目大意:给定一棵树,每条边上有一个权值,找出一条路径,使得路径上权值的亦或和最大. 解题思路:dfs一遍,预处理出每个节点到根节点路径的亦或和rec,那么任意路径均可以表示rec[a] ^ rec[b],所以问题 就转换成在一些数中选出两个数亦或和最大,那么就建立字典树查询即可. #include <cstdio> #include <cstring> #include <algorithm> us

字典树

字典树(Trie)是一种很特别的树状信息检索数据结构,如同其名,它的构成就像一本字典,可以让你快速的进行字符插入.字符串搜索等. Trie 一词来自 retrieval,发音为 /tri:/ "tree",也有人读为 /tra?/ "try". 字典树设计的核心思想是空间换时间,所以数据结构本身比较消耗空间.但它利用了字符串的共同前缀(Common Prefix)作为存储依据,以此来节省存储空间,并加速搜索时间.Trie 的字符串搜索时间复杂度为 O(m),m 为最