• SPOJ COT Count on a tree(可持久化线段树+倍增lca)


    题意:给你颗树,灭个节点都有一个权值,询问你a到b上的路径的地k小

    思路:这个题其实就是树上的第k小,主席树的本质还是类似于前缀和一样的结构,所以是完全相同的,所以我们在树上也可以用同样的方法,我们对于每一个节点进行建树,然后和普通的树上相同,ab之间的距离是等于

    root[a]+root[b]-root[lca[a,b]]-root[fa[lca[a,b]]]

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+7;
    const int POW=18;
    int num[maxn],sa[maxn];
    int ls[maxn*40],rs[maxn*40];
    int sum[maxn*40];
    int root[maxn];
    vector<int>mp[maxn];
    int dis[maxn];
    int p[maxn][POW];
    int cnt;
    int f[maxn];
    
    void build(int l,int r,int &rt)
    {
        rt=++cnt;
        sum[rt]=0;
        if(l>=r)return ;
        int mid=(l+r)>>1;
        build(l,mid,ls[rt]);
        build(mid+1,r,rs[rt]);
    }
    void update(int last,int p,int l,int r,int &rt)
    {
        rt=++cnt;
        ls[rt]=ls[last];
        rs[rt]=rs[last];
        sum[rt]=sum[last]+1;
        if(l>=r)return ;
        int mid=(l+r)>>1;
        if(p<=mid)update(ls[last],p,l,mid,ls[rt]);
        else update(rs[last],p,mid+1,r,rs[rt]);
    }
    int query(int lrt,int rrt,int lcart,int lcafrt,int l,int r,int k)
    {
        if(l>=r)return l;
        int mid=(l+r)>>1;
        int ans=sum[ls[rrt]]+sum[ls[lrt]]-sum[ls[lcart]]-sum[ls[lcafrt]];
        if(k<=ans)
            return query(ls[lrt],ls[rrt],ls[lcart],ls[lcafrt],l,mid,k);
        else
            return query(rs[lrt],rs[rrt],rs[lcart],rs[lcafrt],mid+1,r,k-ans);
    }
    void dfs(int u,int fa,int tot)
    {
        f[u]=fa;
        dis[u]=dis[fa]+1;
        p[u][0]=fa;
        for(int i=1;i<POW;i++)
            p[u][i]=p[p[u][i-1]][i-1];
        update(root[fa],num[u],1,tot,root[u]);
        for(int i=0;i<mp[u].size();i++){
            int v=mp[u][i];
            if(v==fa)continue;
            dfs(v,u,tot);
        }
    }
    int lca(int a,int b)
    {
        if(dis[a]>dis[b])swap(a,b);
        if(dis[a]<dis[b]){
            int del=dis[b]-dis[a];
            for(int i=0;i<POW;i++)
                if(del&(1<<i))b=p[b][i];
        }
        if(a!=b){
            for(int i=POW-1;i>=0;i--){
                if(p[a][i]!=p[b][i]){
                    a=p[a][i];b=p[b][i];
                }
            }
            a=p[a][0];b=p[b][0];
        }
        return a;
    }
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m)){
            for(int i=0;i<n;i++)mp[i].clear();
            memset(dis,0,sizeof(dis));
            memset(p,0,sizeof(p));
            memset(f,0,sizeof(f));
            for(int i=1;i<=n;i++){
                scanf("%d",&num[i]);
                sa[i]=num[i];
            }
            cnt=0;
            sort(sa+1,sa+1+n);
            int tot=unique(sa+1,sa+1+n)-sa-1;
            for(int i=1;i<=n;i++){
                num[i]=lower_bound(sa+1,sa+tot+1,num[i])-sa;
            }
            int a,b,c;
            for(int i=1;i<n;i++){
                scanf("%d%d",&a,&b);
                mp[a].push_back(b);
                mp[b].push_back(a);
            }
            build(1,tot,root[0]);
            dfs(1,0,tot);
            for(int i=1;i<=m;i++){
                scanf("%d%d%d",&a,&b,&c);
                int t=lca(a,b);
                int id=query(root[a],root[b],root[t],root[f[t]],1,tot,c);
                printf("%d
    ",sa[id]);
            }
        }
        return 0;
    }
    /*
    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
    2 5 2
    2 5 3
    2 5 4
    7 8 2
    */
  • 相关阅读:
    深度css: 层级树及zindex属性
    点“九”切图教程分享
    简析 iOS 程序图标的设计
    网站打开时Waiting(TTFP)时间反应很久的问题解决
    CentOS最小化安装网卡ens33没有IP地址问题解决
    怎么使用XShell远程连接服务器?
    Linux发行版时间线分支图最新版
    pstree命令找不到解决方法
    解决网站出现Error Establishing Database Connection问题
    图片地址
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9340429.html
Copyright © 2020-2023  润新知