zoukankan      html  css  js  c++  java
  • 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不会做然后学了一下。。
     题意:路径u->v上与x异或的最大值是多少
     
    我觉得这个可持续字典树的写法有点像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 ",mx);
        }
       }
    }
     
     
  • 相关阅读:
    仿联想商城laravel实战---6、自建配置文件和缓存(如何读取自己创建的配置文件的信息)
    php中相对路径和绝对路径如何使用(详解)
    英语影视台词---绿皮书(2)(利普 我以为你要把那家伙打死了)
    仿联想商城laravel实战---5、无刷新的增删改查(动态页面更新的三种方式(html))
    英语发音规则---ea字母组合发音规律
    英语发音规则---ir字母组合发音规律
    仿联想商城laravel实战---4、验证(lavarel的表单验证如何使用)
    android adb 不同的方式使用特定的解释
    Spring aop 小例子demo
    SPOJ 15. The Shortest Path 堆优化Dijsktra
  • 原文地址:https://www.cnblogs.com/mfys/p/7466575.html
Copyright © 2011-2022 走看看