hdu4757 Tree

原创 2013年09月21日 20:15:52

可持久化Trie,比赛的时候一直在想不到怎么样才可以做减法,赛后才想清楚。

首先异或最大就是在字典树上找它的按位取反,首先满足高位。

对每个节点维护一个Trie,维护的是它到根所有路过的节点的权值,维护Trie的时候同时维护一下子树的叶子节点个数。

对于每一个询问先倍增求出LCA,再由三个节点的权值来计算某子树的叶子节点个数,判断能不能走到某个儿子,如果某棵子树没有叶子节点就意味着不能走。

说的比较抽象,看代码比较好懂吧。。大概

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 100010
#define M 2000000
int u[M][2] , v[M] , cnt;
int n , m , a[N] , L[N] , f[17][N] , pre[N] , mcnt;
struct edge
{
    int x , next;
}e[N << 1];
int str[20];
int root[N];
int newnode()
{
    memset(u[cnt] , 0 , sizeof(u[cnt]));
    v[cnt] = 0;
    return cnt ++;
}

void insert(int x , int y , int val)
{
    x = root[x] , y = root[y];
    for (int i = 0 ; i < 16 ; ++ i)
    {
        int c = val >> (16 - i - 1) & 1;
        if (!u[x][c])
          u[x][c] = newnode() , u[x][!c] = u[y][!c] , v[u[x][c]] = v[u[y][c]];
        x = u[x][c] , y = u[y][c];
        ++ v[x];
    }
}
int query(int x , int y , int z , int val)
{
    int ans = 0 , res = a[z] ^ val;
    x = root[x] , y = root[y] , z = root[z];
    for (int i = 0 ; i < 16 ; ++ i)
    {
        int c = !(val >> (16 - i - 1) & 1);
        if (v[u[x][c]] + v[u[y][c]] - v[u[z][c]] - v[u[z][c]] > 0)
            ans |= 1 << (16 - i - 1);
        else
            c = !c;
        x = u[x][c] , y = u[y][c] , z = u[z][c];
    }
    return max(ans , res);
}


void dfs(int x , int fa)
{
    f[0][x] = fa , L[x] = L[fa] + 1 ;
    root[x] = newnode();
    insert(x , fa , a[x]);
    for (int i = pre[x] ; ~i ; i = e[i].next)
        if (e[i].x != fa)
            dfs(e[i].x , x);
}

int LCA(int x , int y)
{
    if (L[x] > L[y]) swap(x , y);
    for (int i = 16 ; i >= 0 ; -- i)
        if (L[y] - L[x] >= 1 << i)
            y = f[i][y];
    if (x == y) return y;
    for (int i = 16 ; i >= 0 ; -- i)
        if (f[i][x] && f[i][x] != f[i][y])
            x = f[i][x] , y = f[i][y];
    return f[0][x];
}

void work()
{
    int  i , j , x , y , z , w;
    memset(pre , -1 , sizeof(pre));
    mcnt = 0 , cnt = 1;
    for (i = 1 ; i <= n ; ++ i)
        scanf("%d",&a[i]);
    for (i = 1 ; i < n ; ++ i)
    {
        scanf("%d%d",&x,&y);
        e[mcnt].x = y , e[mcnt].next = pre[x] , pre[x] = mcnt ++;
        e[mcnt].x = x , e[mcnt].next = pre[y] , pre[y] = mcnt ++;
    }
    memset(f , 0 , sizeof(f));
    dfs(1 , 0);
    for (j = 1 ; 1 << j < n ; ++ j)
        for (i = 1 ; i <= n ; ++ i)
            f[j][i] = f[j - 1][f[j - 1][i]];
    while (m --)
    {
        scanf("%d%d%d",&x,&y,&w);
        z = LCA(x , y);
        printf("%d\n" , query(x , y , z , w));
    }
}

int main()
{
    freopen("~input.txt" , "r" , stdin);
    while (~scanf("%d%d",&n,&m))
        work();
    return 0;
}


hdu 4757 Tree(可持久化Trie)

题意:给出一棵树,每个点上有权值,有m组询问,每次询问从x到y的路径上的权值与z异或的最大值为多少。 思路:把每个点的权值用二进制表示,然后插入Trie。利用可持久化Trie可以查询历史信息的特点,...
  • qian99
  • qian99
  • 2014-02-14 09:31:18
  • 1100

hdu 4757 Tree(可持久化字典树)

题目链接:hdu 4757 Tree 题目大意:给定一棵树,每个节点有一个值,现在有Q次询问,每次询问u到v路径上节点值与w亦或值的最大值。 解题思路:刚开始以为是树链剖分,其实树链剖分只是用来求...
  • u011328934
  • u011328934
  • 2014-10-30 18:27:49
  • 2653

HDU6191(dfs序 + 可持久Trie树)

Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Oth...
  • creatorx
  • creatorx
  • 2017-08-31 19:50:26
  • 603

HDU 4757 Tree (倍增算法求LCA + 可持久化Trie树)

题目大意: 就是现在给出一棵树, 结点个数不超过10W, 每个节点上有一个不超过2^16的非负整数, 然后10W次询问, 每次询问两个节点的路径上的所有数中异或上给出的数的最大值 大致思路...
  • u013738743
  • u013738743
  • 2015-10-05 21:58:16
  • 828

hdu4757 Tree

可持久化Trie,比赛的时候一直在想不到怎么样才可以做减法,赛后才想清楚。 首先异或最大就是在字典数上找它的按位取反,首先满足高位。 维护Trie的时候同时维护一下子树的叶子节点和,这样就可以做一个减...
  • Sd_Invol
  • Sd_Invol
  • 2013-09-21 20:15:52
  • 2554

hdu-4757-Tree-树链剖分+可持久化字典树

http://acm.hdu.edu.cn/showproblem.php?pid=4757 这题就是n个点,一棵树,n-1条边 m次询问,询问为 (x,y,z)问x到y的路径上哪一个数与z异...
  • viphong
  • viphong
  • 2016-08-10 11:32:40
  • 373

HDU 4757 可持久化trie树

思路: 可持久化trie树裸题 x->y 就是x +y -lca(x,y) -fa[lca(x,y)] 学了可持久化线段树 再看这个就无压力了注意是多组数据……//By SiriusRen #...
  • qq_31785871
  • qq_31785871
  • 2017-01-12 23:35:28
  • 721

Tree HDU4757

http://acm.hdu.edu.cn/showproblem.php?pid=4757 函数式trie,和cot差不多,用父节点递推建立子节点,此题学到了一个函数式的小技巧,就是一开始(即...
  • gyarenas
  • gyarenas
  • 2013-10-03 18:00:01
  • 601

hdu 4757 Tree

Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...
  • Zhuhuangjian
  • Zhuhuangjian
  • 2014-07-26 11:11:35
  • 801

[HDU4757][可持久化Trie][LCA]Tree[好题]

[HDU4757][可持久化Trie][LCA]Tree[好题]
  • BenjaminPMLee
  • BenjaminPMLee
  • 2015-05-06 21:28:21
  • 436
收藏助手
不良信息举报
您举报文章:hdu4757 Tree
举报原因:
原因补充:

(最多只允许输入30个字)