zoukankan      html  css  js  c++  java
  • BZOJ 2588: Spoj 10628. Count on a tree | 树上主席树

    题目:

    求树上两点之间第k小点权


    题解:

    对每个节点到根节点的路径建一棵线段树,这样每个点的线段树都从他父亲得到

    对于询问(u,v),sum[u]+sum[v]-sum[lca]-sum[fa[lca]]可以表示u到v的路径

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define N 200010
    using namespace std;
    int root[N],fa[N],n,m,lastans,w[N],head[N],b[N],lim,pcnt,anc[N][25],ecnt,deep[N];
    struct node {int lc,rc,sum;}t[N*20];
    struct edge {int nxt,v;}e[2*N];
    void add(int u,int v)
    {
        e[++ecnt].v=v;e[ecnt].nxt=head[u];head[u]=ecnt;
        e[++ecnt].v=u;e[ecnt].nxt=head[v];head[v]=ecnt;
    }
    void Insert(int x,int &y,int l,int r,int k)
    {
        t[y=++pcnt]=t[x];t[y].sum++;
        if (l==r) return ;
        int mid=l+r>>1;
        if (k<=mid) Insert(t[x].lc,t[y].lc,l,mid,k);
        else Insert(t[x].rc,t[y].rc,mid+1,r,k);
    }
    void dfs(int u)
    {
        deep[u]=deep[anc[u][0]]+1;
        Insert(root[anc[u][0]],root[u],1,lim,w[u]);
        for (int i=head[u],v;i;i=e[i].nxt)
        if (e[i].v!=anc[u][0])
            anc[v=e[i].v][0]=u,dfs(v);
    }
    int lca(int x,int y)
    {
        if (deep[x]<deep[y]) swap(x,y);
        for (int i=20;i>=0;i--)
            if (deep[anc[x][i]]>=deep[y]) 
                x=anc[x][i];
        if (x==y) return x;
        for (int i=20;i>=0;i--)
            if (anc[x][i]!=anc[y][i])
                x=anc[x][i],y=anc[y][i];
        return anc[x][0];
    }
    int query(int u,int v,int k)
    {
        int GGfa=lca(u,v),tmp[4]={root[u],root[v],root[GGfa],root[anc[GGfa][0]]},val,l=1,r=lim,mid;
        while (l<r)
        {
              mid=l+r>>1;
               val=t[t[tmp[0]].lc].sum+t[t[tmp[1]].lc].sum-t[t[tmp[2]].lc].sum-t[t[tmp[3]].lc].sum;
               if (k<=val)
            {
                r=mid;
                    for (int i=0;i<4;i++)
                    tmp[i]=t[tmp[i]].lc;
               }    
               else
                {
                   l=mid+1;k-=val;
                   for (int i=0;i<4;i++)
                       tmp[i]=t[tmp[i]].rc;
                }
        }
        return b[l];
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) 
            scanf("%d",w+i),b[i]=w[i];
        sort(b+1,b+n+1);
        lim=unique(b+1,b+1+n)-b-1;
        for (int i=1;i<=n;i++)
            w[i]=lower_bound(b+1,b+1+lim,w[i])-b;
        for (int i=1,u,v;i<n;i++)
               scanf("%d%d",&u,&v),add(u,v);
        dfs(1);
        for (int j=1;j<=20;j++)
            for (int i=1;i<=n;i++)
                   anc[i][j]=anc[anc[i][j-1]][j-1];
        for (int i=1,u,v,k;i<=m;i++)
        {
              scanf("%d%d%d",&u,&v,&k);
              printf("%d",lastans=query(u^lastans,v,k));
               if (i<m) printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    Html笔记(四)图像
    Html笔记(三)列表
    Html笔记(二)字体
    Html笔记(一)概述
    mysql基础~经典题目
    MGR架构~原理细节分析(8.0最新版)
    hiveserver2
    恋爱心理
    和谐之道
    智者遇事求心,庸者遇事求境
  • 原文地址:https://www.cnblogs.com/mrsheep/p/8158778.html
Copyright © 2011-2022 走看看