zoukankan      html  css  js  c++  java
  • 【BZOJ2588】Count On a Tree(主席树)

    【BZOJ2588】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

    题解

    链上的第k大->主席树
    这题怎么搞得话
    对于每一个节点建立一个线段树(显然开不下)
    每个节点继承父节点再加上自己
    主席树搞一下
    查询的时候,跳(u,v,lca,father(lca))四棵线段树就行了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 110000
    #define lson (t[now].ls)
    #define rson (t[now].rs)
    inline int read()
    {
        int x=0,t=1;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    struct Line
    {
        int v,next;
    }e[MAX<<1];
    int h[MAX],cnt=1;
    int n,m,sum;
    int a[MAX],S[MAX],tot,z[MAX];
    int rt[MAX];
    struct Node
    {
        int ls,rs;
        int v;
    }t[MAX<<5];
    inline void Add(int u,int v)
    {
        e[cnt]=(Line){v,h[u]};
        h[u]=cnt++;
    }
    void Build(int &now,int l,int r)
    {
        now=++tot;
        if(l==r)return;
        int mid=(l+r)>>1;
        Build(lson,l,mid);
        Build(rson,mid+1,r);
    }
    void Update(int &now,int ff,int l,int r,int pos)
    {
        now=++tot;
        t[now]=t[ff];
        t[now].v++;
        if(l==r)return;
        int mid=(l+r)>>1;
        if(pos<=mid)Update(lson,t[ff].ls,l,mid,pos);
        else Update(rson,t[ff].rs,mid+1,r,pos);
    }
    int Query(int r1,int r2,int r3,int r4,int l,int r,int k)
    {
        if(l==r)return l;
        int tmp=t[t[r1].ls].v+t[t[r2].ls].v-t[t[r3].ls].v-t[t[r4].ls].v;
        int mid=(l+r)>>1;
        if(k<=tmp)return Query(t[r1].ls,t[r2].ls,t[r3].ls,t[r4].ls,l,mid,k);
        else return Query(t[r1].rs,t[r2].rs,t[r3].rs,t[r4].rs,mid+1,r,k-tmp);
    }
    int hson[MAX],fa[MAX],size[MAX],dep[MAX],top[MAX];
    void dfs1(int u,int ff)
    {
        fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1;
        Update(rt[u],rt[ff],1,sum,a[u]);
        for(int i=h[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(v==ff)continue;
            dfs1(v,u);
            size[u]+=size[v];
            if(size[v]>size[hson[u]])hson[u]=v;
        }
    }
    void dfs2(int u,int tp)
    {
        top[u]=tp;
        if(hson[u])dfs2(hson[u],tp);
        for(int i=h[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(v==fa[u]||v==hson[u])continue;
            dfs2(v,v);
        }
    }
    int LCA(int u,int v)
    {
        while(top[u]!=top[v])
        {
            if(dep[top[u]]<dep[top[v]])swap(u,v);
            u=fa[top[u]];
        }
        return dep[u]<dep[v]?u:v;
    }
    int main()
    {
        n=sum=read();m=read();
        for(int i=1;i<=n;++i)S[i]=a[i]=z[i]=read();
        sort(&S[1],&S[n+1]);
        sum=unique(&S[1],&S[sum+1])-S-1;
        for(int i=1;i<=n;++i)a[i]=(lower_bound(&S[1],&S[sum+1],a[i])-S);
        for(int i=1;i<n;++i)
        {
            int x=read(),y=read();
            Add(x,y);Add(y,x);
        }
        Build(rt[0],1,sum);
        dfs1(1,0);dfs2(1,1);
        int lans=0;
        while(m--)
        {
            int u=read()^lans,v=read(),k=read();
            int lca=LCA(u,v);
            printf("%d
    ",lans=S[Query(rt[u],rt[v],rt[lca],rt[fa[lca]],1,sum,k)]);
        }
        return 0;
    }
    
    
  • 相关阅读:
    整型表示
    有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
    shell排序算法实现
    一些小细节
    wordpress新注册用户或重置密码链接失效
    wordpress访问速度慢
    mysql主从复制
    mysql root密码忘记
    mysql root用户登录后无法查看数据库全部表
    Ansible
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8110827.html
Copyright © 2011-2022 走看看