zoukankan      html  css  js  c++  java
  • lightoj-1128-Greatest Parent(二分+LCA)

    传送门

    首先我要实力吐槽这个lightoj

    它给我的注册密码藏在不为人所见的地方

    注册注册了10多分钟

    qwq

    ----------------------------------------------------------------

    其次我要再吐槽一下这个难懂的题目

    全英文emm...

    百度翻译都救不了我

    (我画图花半天,才懂emm...)

    --------------------------------------------------------------

    好的

    我还是先解释一下题目吧

    最最最一开始给你一个t

    一共要整t次(t个不同的树)

    每次的根节点的编号都为0

    先给你2个数n、m

    n个节点的树

    m次询问

    接下来的n-1行

    第i行(1 <= i <= n-1)也有两个数x,y

    x为i点的父节点的编号

    y为i点的权值

    再接下来的m行为m次询问

    每行也有两个数x,y

    每次查询x的父节点中,权值大于或等于y,离x最远的节点,输出它的编号

    ----------------------------------------------------------------------------------------------------------

    基于倍增LCA思想上又用了二分

    和倍增LCA一样

    首先需要预处理出来fa[ ][ ]数组

    于是就开始二分找到最深的节点

    ---------------------------------------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #define N 500100
    using namespace std;
    
    int n,m,dn[N],fa[N][25],dq,last,t,tt;
    
    inline int lca(int l,int r)
    {
        last--;
        if(l == r || dn[l] >= dq && dn[fa[l][0]] < dq)
            return l;
        while((fa[l][last] == -1) || dn[fa[l][last]] < dn[r])
            last--;
        if(dn[fa[l][last]] < dq)
            return lca(l,fa[l][last]);
        else if(dn[fa[l][last]] > dq)
            return lca(fa[l][last],r);
        return fa[l][last];
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        int tt = t;
        while(t--)
        {
            memset(fa,-1,sizeof(fa));
            scanf("%d%d",&n,&m);
            for(int i = 1; i < n; i++)
            {
                int x ,y;
                scanf("%d%d",&x,&y);
                dn[i] = y;
                fa[i][0] = x;
            }
            dn[0] = 1;
            printf("Case %d:
    ",tt - t);
            
            for(int i = 0; i < n; i++)
            {
                for(int j=1; j <= 20; j++)
                {
                    if(fa[i][j - 1] == -1)
                        continue;//超出深度 
                    fa[i][j] = fa[fa[i][j-1]][j - 1];
                }
            }
            
            for(int i = 1; i <= m; i++)
            {
                last = 20;
                int x;
                scanf("%d%d",&x,&dq);
                printf("%d
    ",lca(x,0));
            }
        }
        return 0;
    }
  • 相关阅读:
    Android开源demo---芒果TV-VIP电影播放器
    实现sqrt()函数
    std::string内容包含双引号
    解决win10 SVN不显示绿色和红色的状态显示标志
    win 10 解决 caps键无法退出大写的问题
    webrtc 编译问题:running depot tools as root is sad 的解决办法
    Linux下运行脚本显示“: /usr/bin/env: "bash ": 没有那个文件或目录
    解决报错:no acceptable C compiler found in $PATH when installing python
    linux 打开文件管理器
    windows打开U盘提示 文件或目录损坏且无法读取 解决办法
  • 原文地址:https://www.cnblogs.com/darlingroot/p/10606544.html
Copyright © 2011-2022 走看看