zoukankan      html  css  js  c++  java
  • 洛谷 P2633 Count on a tree

    题目描述

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

    输入输出格式

    输入格式:

     

    第一行两个整数N,M。

    第二行有N个整数,其中第i个整数表示点i的权值。

    后面N-1行每行两个整数(x,y),表示点x到点y有一条边。

    最后M行每行两个整数(u,v,k),表示一组询问。

     

    输出格式:

     

    M行,表示每个询问的答案。

     

    输入输出样例

    输入样例#1:
    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
    输出样例#1:
    2
    8
    9
    105
    7

    说明

    HINT:

    N,M<=100000

    暴力自重。。。

    来源:bzoj2588 Spoj10628.

    本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。

    思路:主席树+LCA

    以点的dfs序为下标,以点权为区间建立主席树

    以前做过的主席树在序列上,所以是以前一个节点的线段树为基准建立的

    这里在树上,所以可以考虑以根为基准建立线段树

    u,v间增加的点数=cnt[u]+cnt[v]-cnt[LCA(u,v)]-cnt[father[LCA(u,v)]]

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100001
    using namespace std;
    int n,m,tot,cnt,num,lastans;
    int a[MAXN],ha[MAXN],root[MAXN];
    int to[MAXN*2],net[MAXN*2],head[MAXN*2];
    int top[MAXN],dad[MAXN],deep[MAXN],size[MAXN];
    struct nond{
        int l,r,cnt;
    }tree[MAXN*20];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
        to[++tot]=u;net[tot]=head[v];head[v]=tot;
    }
    void insert(int pre,int &now,int l,int r,int k){
        tree[now=++num].cnt=tree[pre].cnt+1;
        if(l==r)    return ;
        int mid=(l+r)/2;
        if(k<=mid){
            tree[now].r=tree[pre].r;
            insert(tree[pre].l,tree[now].l,l,mid,k);
        }
        else{
            tree[now].l=tree[pre].l;
            insert(tree[pre].r,tree[now].r,mid+1,r,k);
        }
    }
    int query(int x,int y,int LCA,int fa_LCA,int l,int r,int k){
        if(l==r)    return a[l];
        int mid=(l+r)/2;
        int tmp=tree[tree[x].l].cnt+tree[tree[y].l].cnt-tree[tree[LCA].l].cnt-tree[tree[fa_LCA].l].cnt;
        if(k<=tmp)    query(tree[x].l,tree[y].l,tree[LCA].l,tree[fa_LCA].l,l,mid,k);
        else    query(tree[x].r,tree[y].r,tree[LCA].r,tree[fa_LCA].r,mid+1,r,k-tmp);
    }
    void dfs(int now){
        size[now]=1;
        insert(root[dad[now]],root[now],1,cnt,ha[now]);
        deep[now]=deep[dad[now]]+1;
        for(int i=head[now];i;i=net[i])
            if(dad[now]!=to[i]){
                dad[to[i]]=now;
                dfs(to[i]);
                size[now]+=size[to[i]];
            }
    }
    void dfs1(int x){
        int t=0;
        if(top[x]==0)    top[x]=x;
        for(int i=head[x];i;i=net[i])
            if(dad[x]!=to[i]&&size[to[i]]>size[t])
                t=to[i];
        if(t){
            top[t]=top[x];
            dfs1(t);
        }
        for(int i=head[x];i;i=net[i])
            if(dad[x]!=to[i]&&t!=to[i])
                dfs1(to[i]);
    }
    int lca(int x,int y){
        for(;top[x]!=top[y];){
            if(deep[top[x]]<deep[top[y]])
                swap(x,y);
            x=dad[top[x]];
        }
        if(deep[x]>deep[y])
            swap(x,y);
        return x;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            ha[i]=a[i];
        }
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        sort(a+1,a+1+n);
        cnt=unique(a+1,a+1+n)-(a+1);
        for(int i=1;i<=n;i++)
            ha[i]=lower_bound(a+1,a+1+cnt,ha[i])-a;
        dfs(1);
        dfs1(1);
        for(int i=1;i<=m;i++){
            int u,v,k;
            scanf("%d%d%d",&u,&v,&k);
            u^=lastans;
            int LCA=lca(u,v);
            lastans=query(root[u],root[v],root[LCA],root[dad[LCA]],1,cnt,k);
            if(i!=m)    cout<<lastans<<endl;
            else cout<<lastans;
        }
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    ruby 实现java中的aes 加密解密
    移动端手机端web页面中背景图固定问题
    hooks 组件对应的生命周期
    React 生命周期函数总结
    Sequelize 常用增删改查函数
    如何验证SSH的连通性
    如何生成SSH密钥
    如何查看本机ssh秘钥
    如何更改本地代码仓库指向
    如何发布npm 包
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7603653.html
Copyright © 2011-2022 走看看