• AC日记——Count on a tree bzoj 2588


    Description

    给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
     

    Input

    第一行两个整数N,M。
    第二行有N个整数,其中第i个整数表示点i的权值。
    后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
    最后M行每行两个整数(u,v,k),表示一组询问。
     

    Output

    M行,表示每个询问的答案。最后一个询问不输出换行符

    Sample Input

    8 5
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5 1
    0 5 2
    10 5 3
    11 5 4
    110 8 2

    Sample Output

    2
    8
    9
    105
    7

    HINT




    HINT:

    N,M<=100000

    暴力自重。。。
     
    思路:
      主席树;
      树上一段路径中主席树的状态可以用root[from]+root[to]-root[lca]-root[f[lca]]来表示
      但是,这个题和spoj上不太一样
      要用到long long
      而且每次的from都是一个二进制数,需要xor上一次查询的答案;
     
    来,上代码:
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define LL long long
    #define maxn 100001
    
    using namespace std;
    
    struct TreeNodeType {
        LL dis,lc,rc;
    };
    struct TreeNodeType tree[maxn*45];
    
    struct EdgeType {
        LL to,next;
    };
    struct EdgeType edge[maxn<<1];
    
    LL if_z,n,m,hash[maxn],hash_[maxn],cnt,head[maxn];
    LL size_,tot,root[maxn],deep[maxn],f[maxn],size[maxn];
    LL belong[maxn];
    
    char Cget;
    
    inline void read_int(LL &now)
    {
        now=0,if_z=1,Cget=getchar();
        while(Cget>'9'||Cget<'0')
        {
            if(Cget=='-') if_z=-1;
            Cget=getchar();
        }
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
        now*=if_z;
    }
    
    inline void edge_add(LL from,LL to)
    {
        cnt++;
        edge[cnt].to=to;
        edge[cnt].next=head[from];
        head[from]=cnt;
    }
    
    void tree_build(LL now,LL l,LL r)
    {
        tree[now].dis=0;
        if(l==r) return ;
        LL mid=(l+r)>>1;
        tree[now].lc=++tot;
        tree_build(tot,l,mid);
        tree[now].rc=++tot;
        tree_build(tot,mid+1,r);
    }
    
    void tree_add(LL pre,LL now,LL to,LL l,LL r)
    {
        tree[now].dis=tree[pre].dis+1;
        if(l==r) return ;
        LL mid=(l+r)>>1;
        if(to>mid)
        {
            tree[now].lc=tree[pre].lc;
            tree[now].rc=++tot;
            tree_add(tree[pre].rc,tree[now].rc,to,mid+1,r);
        }
        else
        {
            tree[now].rc=tree[pre].rc;
            tree[now].lc=++tot;
            tree_add(tree[pre].lc,tree[now].lc,to,l,mid);
        }
    }
    
    void search(LL now,LL pre)
    {
        LL pos=cnt++;
        f[now]=pre;
        deep[now]=deep[pre]+1;
        hash_[now]=lower_bound(hash+1,hash+size_+1,hash_[now])-hash;
        root[now]=++tot;
        tree_add(root[pre],root[now],hash_[now],1,size_);
        for(LL i=head[now];i;i=edge[i].next)
        {
            if(edge[i].to==pre) continue;
            search(edge[i].to,now);
        }
        size[now]=cnt-pos;
    }
    
    void search_(LL now,LL chain)
    {
        LL pos=0;
        belong[now]=chain;
        for(LL i=head[now];i;i=edge[i].next)
        {
            if(edge[i].to==f[now]) continue;
            if(size[edge[i].to]>size[pos]) pos=edge[i].to;
        }
        if(pos==0) return ;
        search_(pos,chain);
        for(LL i=head[now];i;i=edge[i].next)
        {
            if(pos==edge[i].to||edge[i].to==f[now]) continue;
            search_(edge[i].to,edge[i].to);
        }
    }
    
    inline LL tree_lca(LL x,LL y)
    {
        while(belong[x]!=belong[y])
        {
            if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
            x=f[belong[x]];
        }
        if(deep[x]<deep[y]) return x;
        else return y;
    }
    
    inline LL tree_query(LL x,LL y,LL lca,LL flca,LL l,LL r,LL k)
    {
        LL dis,mid;
        while(l!=r)
        {
            dis=tree[tree[x].lc].dis+tree[tree[y].lc].dis-tree[tree[lca].lc].dis-tree[tree[flca].lc].dis;
            mid=(l+r)>>1;
            if(k>dis)
            {
                k-=dis;
                l=mid+1;
                lca=tree[lca].rc;
                flca=tree[flca].rc;
                x=tree[x].rc,y=tree[y].rc;
            }
            else
            {
                r=mid;
                lca=tree[lca].lc;
                flca=tree[flca].lc;
                x=tree[x].lc,y=tree[y].lc;
            }
        }
        return l;
    }
    
    int main()
    {
        read_int(n),read_int(m);
        for(LL i=1;i<=n;i++)
        {
            read_int(hash[i]);
            hash_[i]=hash[i];
        }
        LL from,to;
        for(LL i=1;i<n;i++)
        {
            read_int(from),read_int(to);
            edge_add(from,to);
            edge_add(to,from);
        }
        sort(hash+1,hash+n+1);
        size_=unique(hash+1,hash+n+1)-hash-1;
        root[0]=++tot;
        tree_build(root[0],1,size_);
        cnt=0,search(1,0);
        cnt=0,search_(1,1);
        LL K,last=0;
        for(LL i=1;i<=m;i++)
        {
            read_int(from),read_int(to),read_int(K);
            from=from^last;
            LL lca=tree_lca(from,to);
            last=hash[tree_query(root[from],root[to],root[lca],root[f[lca]],1,size_,K)];
            if(i!=m) printf("%lld
    ",last);
            else printf("%lld",last);
        }
        return 0;
    }
  • 相关阅读:
    104.求二叉树的最大深度 Maximum Depth of Binary Tree
    389.查出两个字符串中 不同的字母 Find the Difference
    455.分配饼干问题 Assign Cookies
    412.数组下标的倍数 Fizz Buzz
    344.反转字符串 Reverse String
    jQuery笔记
    仿淘宝返回顶部 (带有动画的返回顶部)
    网页轮播图(功能最全)
    js 元素offset,client , scroll 三大系列总结
    仿淘宝固定侧边栏
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6382286.html
Copyright © 2020-2023  润新知