zoukankan      html  css  js  c++  java
  • BZOJ2588Count on a tree——LCA+主席树

    题目描述

    给定一棵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行,表示每个询问的答案。最后一个询问不输出换行符

    样例输入

    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

    样例输出

    2
    8
    9
    105
    7

    提示

    HINT:
    N,M<=100000
     
      
      查询一个路径上第k小,就相当于查询序列上区间第k小,可以想到用主席树维护。但这道题是在树上完成的操作,所以并不能像平常主席树一样只用r时刻减掉l-1时刻的线段树查询。对于树上的路径(以x和y之间的路径为例),可以把它分成两部分:x到lca和y到lca。这样整条路径上的信息就可以通过这两条链相加得到。所以直接用x时刻线段树+y时刻线段树-lca时刻线段树-lca的父节点时刻线段树就得到路径上状态。每个时刻线段树由它的父节点时刻线段树转移过来。
    最后附上代码。
    #include<map>
    #include<set>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mid (L+R)/2
    using namespace std;
    int ans;
    int tot;
    int cnt;
    int anc;
    int n,m,q;
    int x,y,z;
    int d[100010];
    int v[100010];
    int h[100010];
    int l[3000010];
    int r[3000010];
    int to[200010];
    int head[100010];
    int next[200010];
    int sum[3000010];
    int root[100010];
    int f[100010][20];
    map<int,int>b;
    void add(int x,int y)
    {
        tot++;
        next[tot]=head[x];
        head[x]=tot;
        to[tot]=y;
    }
    int lca(int x,int y)
    {
        if(d[x]<d[y])
        {
            swap(x,y);
        }
        int dep=d[x]-d[y];
        for(int i=0;i<=19;i++)
        {
            if((dep&(1<<i))!=0)
            {
                x=f[x][i];
            }
        }
        if(x==y)
        {
            return x;
        }
        for(int i=19;i>=0;i--)
        {
            if(f[x][i]!=f[y][i])
            {
                x=f[x][i];
                y=f[y][i];
            }
        }
        return f[x][0];
    }
    int updata(int pre,int L,int R,int k)
    {
        int rt=++cnt;
        l[rt]=l[pre];
        r[rt]=r[pre];
        sum[rt]=sum[pre]+1;
        if(L==R)
        {
            return rt;
        }
        else
        {
            if(k<=mid)
            {
                l[rt]=updata(l[pre],L,mid,k);
            }
            else
            {
                r[rt]=updata(r[pre],mid+1,R,k);
            }
        }
        return rt;
    }
    int query(int x,int y,int anc,int fa,int L,int R,int k)
    {
        if(L==R)
        {
            return b[L];
        }
        int num=sum[l[x]]+sum[l[y]]-sum[l[anc]]-sum[l[fa]];
        if(num>=k)
        {
            return query(l[x],l[y],l[anc],l[fa],L,mid,k);
        }
        else
        {
            return query(r[x],r[y],r[anc],r[fa],mid+1,R,k-num);
        }
    }
    void dfs(int x,int fa)
    {
        d[x]=d[fa]+1;
        int k=lower_bound(h+1,h+1+m,v[x])-h;
        b[k]=v[x];
        root[x]=updata(root[fa],1,n,k);
        for(int i=1;i<=19;i++)
        {
            f[x][i]=f[f[x][i-1]][i-1];
        }
        for(int i=head[x];i;i=next[i])
        {
            if(to[i]!=fa)
            {
                f[to[i]][0]=x;
                dfs(to[i],x);
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&v[i]);
            h[i]=v[i];
        }
        sort(h+1,h+1+n);
        m=unique(h+1,h+1+n)-h-1;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs(1,0);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            x=x^ans;
            anc=lca(x,y);
            ans=query(root[x],root[y],root[anc],root[f[anc][0]],1,n,z);
            printf("%d
    ",ans);
        }
    }
    
  • 相关阅读:
    delphi中屏蔽浏览器控件右键菜单
    书目:一些
    数据库ADONETDataAdapter对象参考
    数据库ADONET排序、搜索和筛选
    易语言数据类型及其长度
    易语言数据类型的初始值
    数据库ADONET使用DataAdapter对象
    ADONET使用DataSet处理脱机数据
    数据库ADONETOleDbParameter对象参考
    在项目中添加新数据集
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9298150.html
Copyright © 2011-2022 走看看