码迷,mamicode.com
首页 > 其他好文 > 详细

HDU4757 Tree(可持久化Trie)

时间:2014-11-04 22:36:12      阅读:332      评论:0      收藏:0      [点我收藏+]

标签:blog   io   ar   os   for   sp   div   on   log   

写过可持久化线段树,但是从来没写过可持久化的Trie,今天补一补。

题目就是典型的给你一个数x,和一个数集,问x和里面的某个数xor起来的最大值是多少。

最原始的是数集是固定的,只需要对数集按照高到低位去建Trie,然后贪心匹配就可以了。

这里则是对树上路径的操作,其实也是一样的,对每个节点x维护root到x的Trie,然后纪录下往左走往右走的叶子节点个数,设z=lca(x,y),那么到了个某个节点能否往某个儿子走的限制条件是 sz[ch[x][c]]+sz[ch[y][c]]-2*sz[ch[z][c]]>0,这样说明下面是存在c的儿子的,接着往下走即可。当然这样算其实是会漏掉lca的,所以最后还要和lca取最大值。

区间的询问作为这题的特例同理也是可以处理的。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cassert>
#include <vector>
#include <set>
using namespace std;

#define maxn 120000
#define maxnode 2200000
#define maxlogv 16
vector<int> G[maxn];
int n,m;
int a[maxn];

int f[maxlogv+2][maxn];
int dep[maxn];
int ch[maxnode][2];
int sz[maxnode];
int tot;
int root[maxn];

int newnode(){
    memset(ch[tot],0,sizeof(ch[tot]));
    sz[tot]=0;
    return tot++;
}

// insert val for x with father as y
void insert(int x,int y,int val)
{
    x=root[x];y=root[y];
    for(int i=15;i>=0;--i){
        int c=(val>>i)&1;
        if(!ch[x][c]){
            int id=newnode();
            ch[x][c]=id;
            ch[x][!c]=ch[y][!c];
            sz[ch[x][c]]=sz[ch[y][c]];
        }
        x=ch[x][c],y=ch[y][c];
        ++sz[x];
    }
}

void dfs(int u,int fa)
{
    f[0][u]=fa;dep[u]=dep[fa]+1;
    root[u]=newnode();
    insert(u,fa,a[u]);
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i];
        if(v==fa) continue;
        dfs(v,u);
    }
}

int lca(int u,int v)
{
    if(dep[u]>dep[v]) swap(u,v);
    for(int k=0;k<maxlogv;++k){
        if( (dep[v]-dep[u])>>k&1){
            v=f[k][v];
        }
    }
    if(u==v) return u;
    for(int k=maxlogv-1;k>=0;--k){
        if(f[k][u]!=f[k][v]){
            u=f[k][u];
            v=f[k][v];
        }
    }
    return f[0][u];
}

int query(int x,int y,int val)
{
    int z=lca(x,y);int res=a[z]^val;
    x=root[x],y=root[y],z=root[z];
    int ret=0;
    for(int i=15;i>=0;--i){
        int c=(val>>i)&1;
        if(sz[ch[x][!c]]+sz[ch[y][!c]]-2*sz[ch[z][!c]]>0){
            ret+=1<<i;
            c=!c;
        }
        x=ch[x][c];
        y=ch[y][c];
        z=ch[z][c];
    }
    return max(ret,res);
}


int main()
{
    while(cin>>n>>m){
        for(int i=1;i<=n;++i){
            scanf("%d",a+i);
            G[i].clear();
        }
        int ui,vi;
        for(int i=0;i<n-1;++i){
            scanf("%d%d",&ui,&vi);
            G[ui].push_back(vi);
            G[vi].push_back(ui);
        }
        memset(root,0,sizeof(root));
        tot=1;
        memset(f,0,sizeof(f));
        memset(sz,0,sizeof(sz));
        dep[0]=0;
        dfs(1,0);
        for(int k=0;k+1<maxlogv;++k){
            for(int v=1;v<=n;++v){
                if(f[k][v]==0) f[k+1][v]=0;
                else f[k+1][v]=f[k][f[k][v]];
            }
        }
        int xi,yi,zi;
        for(int i=0;i<m;++i){
            scanf("%d%d%d",&xi,&yi,&zi);
            printf("%d\n",query(xi,yi,zi));
        }
    }
    return 0;
}

 

HDU4757 Tree(可持久化Trie)

标签:blog   io   ar   os   for   sp   div   on   log   

原文地址:http://www.cnblogs.com/chanme/p/4074858.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!