• spoj COT


    链接:

    https://www.spoj.com/problems/COT/en/

    思路:

    首先看到求两点之前的第k小很容易想到用主席树去写,但是主席树处理的是线性结构,而这道题要求的是树形结构,我们可以用dfs跑出所有点离根的距离-dep[i](根为1,dep[1]也为1)在dfs的过程

    中,我们对每一个节点建一棵线段树,那么【a,b】就是:root[a] + root[b] - root[lca(a,b)] - root[f[lca(a,b)]]; (因为a-b的路径上的权值还要算上lca(a,b)这个点,所以不是减2*root[lca(a,b)]);

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid int m = (l + r) >> 1
    const int M = 2e5 + 10;
    int p[M][30],dep[M],head[M],sum[M*20],ls[M*20],rs[M*20],root[M*20];
    int cnt1,n,idx,cnt,f[M];
    
    struct node {
        int to,next;
    }e[M];
    
    void add(int u,int v){
        e[++cnt1].to=v;e[cnt1].next=head[u];head[u]=cnt1;
        e[++cnt1].to=u;e[cnt1].next=head[v];head[v]=cnt1;
    }
    
    int lca(int a,int b){
        if(dep[a] > dep[b]) swap(a,b);
        int h = dep[b] - dep[a]; //h为高度差
        for(int i = 0;(1<<i)<=h;i++){  //(1<<i)&f找到h化为2进制后1的位置,移动到相应的位置
            if((1<<i)&h) b = p[b][i];
            //比如h = 5(101),先移动2^0祖先,然后再移动2^2祖先
        }
        //cout<<a<<" "<<b<<endl;
        if(a!=b){
            for(int i = 22;i >= 0;i --){
                if(p[a][i]!=p[b][i]){  //从最大祖先开始,判断a,b祖先,是否相同
                    a = p[a][i]; b = p[b][i]; //如不相同,a,b,同时向上移动2^j
                }
            }
            a = p[a][0]; //这时a的father就是LCA
        }
        return a;
    }
    
    void build(int l,int r,int &rt){
        rt = ++idx;
        sum[rt] = 0;
        if(l == r) return;
        mid;
        build(l,m,ls[rt]);
        build(m+1,r,rs[rt]);
    }
    
    void update(int p,int l,int r,int old,int &rt){
        rt = ++idx;
        ls[rt] = ls[old]; rs[rt] = rs[old]; sum[rt] = sum[old] + 1;
        if(l == r) return ;
        mid;
        if(p <= m) update(p,l,m,ls[old],ls[rt]);
        else update(p,m+1,r,rs[old],rs[rt]);
    }
    
    int query(int a,int b,int lc,int cl,int l,int r,int k){
        if(l == r) return l;
        mid;
        int cnt = sum[ls[a]] + sum[ls[b]] - sum[ls[lc]] - sum[ls[cl]];
        if(k <= cnt)
            return query(ls[a],ls[b],ls[lc],ls[cl],l,m,k);
        else
            return query(rs[a],rs[b],rs[lc],rs[cl],m+1,r,k-cnt);
    }
    int a[M],b[M];
    
    void dfs(int u,int fa){
        f[u] = fa;
        dep[u] = dep[fa] + 1;
        p[u][0] = fa;
        for(int i = 1;i < 20;i ++) p[u][i] = p[p[u][i-1]][i-1];
        update(a[u],1,cnt,root[fa],root[u]);
        for(int i = head[u];i!=-1;i = e[i].next){
            int v = e[i].to;
            if(v == fa) continue;
            dfs(v,u);
        }
    }
    
    int main()
    {
        int m;
        while(scanf("%d%d",&n,&m)!=EOF){
            cnt1 = 0;
            memset(head,-1,sizeof(head));
            memset(dep,0,sizeof(dep));
            memset(p,0,sizeof(p));
            memset(f,0,sizeof(f));
            for(int i = 1; i <= n;i ++){
                scanf("%d",&a[i]);
                b[i] = a[i];
            }
            idx = 0;
            int l,r,c;
            sort(b+1,b+n+1);
            cnt = unique(b+1,b+1+n)-b-1;
            for(int i = 1;i <= n;i ++)
                a[i] = lower_bound(b+1,b+cnt+1,a[i]) - b;
            for(int i = 1;i <= n-1;i ++){
                scanf("%d%d",&l,&r);
                add(l,r);
            }
            build(1,cnt,root[0]);
            dfs(1,0);
            for(int i = 1;i <= m;i ++){
                scanf("%d%d%d",&l,&r,&c);
                int lc = lca(l,r);
                int id = query(root[l],root[r],root[lc],root[f[lc]],1,cnt,c);
                printf("%d
    ",b[id]);
            }
        }
        return 0;
    }
  • 相关阅读:
    SQL Azure (17) SQL Azure V12
    Microsoft Azure News(5) Azure新DV2系列虚拟机上线
    Azure Redis Cache (3) 在Windows 环境下使用Redis Benchmark
    Azure PowerShell (11) 使用自定义虚拟机镜像模板,创建Azure虚拟机并绑定公网IP(VIP)和内网IP(DIP)
    Windows Azure Virtual Machine (31) 迁移Azure虚拟机
    Windows Azure Web Site (16) Azure Web Site HTTPS
    Azure China (12) 域名备案问题
    一分钟快速入门openstack
    管理员必备的Linux系统监控工具
    Keepalived+Nginx实现高可用和双主节点负载均衡
  • 原文地址:https://www.cnblogs.com/kls123/p/9397910.html
Copyright © 2020-2023  润新知