zoukankan      html  css  js  c++  java
  • [LightOJ 1128]Greatest Parent

    原题链接:http://www.lightoj.com/volume_showproblem.php?problem=1128

    原题是英文题面,大概翻译了一下:

    最大的祖先

    树是一个连通的无环图,在这个问题中给出一个有根树,每个点有一个权值,每个点的权值严格的大于它父亲的权值。现在给出一个点以及一个整数的询问,你需要找到这个点最大的可能的祖先(也许可能包括这个点),它的权值大于或等于给出的整数。

    输入

    输入的开始是一个整数 T (T≤ 5), 表示测试数据的数量。

    每一个情况的第一行是一个空行,下一列读入两个整数 N (1 ≤ N ≤ 105)q (1 ≤ q ≤ 50000) N表示点的个数,q表示询问的个数。点的标记从0到N-1。

    然后将会有N-1行,第i行 (1 ≤ i < N) 包括两个整数 pi 和 si (0 ≤ pi < i, 1 ≤ si < 231)pi 表示这个点的父亲,si 表示这个点的权值。假设给出的树是正确的然后下面的限制是存在的。你可以假设第0个点为根节点并且它的点权为1。

    以下q行每行包括一个询问,每个询问包括两个整数k和v (1 ≤ k < N, 1 ≤ v ≤ sk).

    输出

    对于每个情况,在一行输出情况编号,然后对于每个询问,输出最大的,点权大于等于v的祖先的编号k。你可以假设解是存在的。.

    样例输入

    样例输出

    1

     

    7 4

    0 3

    0 4

    0 2

    1 4

    2 7

    2 10

    5 1

    4 2

    5 4

    6 10

    Case 1:

    0

    1

    2

    6

      因为是英文题面,在看题的时候难免有所疏漏或者理解错误,尤其是输入输出格式(之前因为要输出caseWA了n次)。一旦我们知道了输入输出格式,在仔细看题就不是特别复杂了。给出的这棵树满足儿子节点的点权一定比父亲大,那么我们可以利用倍增的思想解决问题,让x按照倍增方式不断向上爬,每爬到一个点就看看这个点的点权和询问的数相比哪个大,满足条件输出结果。如果不是倍增,一步一步向上复杂度为O(n),会被卡,而倍增为O(logn),可以通过。

    参考代码

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #define ll int
    #define N 200010
    #define mm(a) memset(a,0,sizeof(a))
    ll read()
    {
        char ch = getchar();
        ll x = 0, f = 1;
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') f = -1;
            ch = getchar();
        }
        while('0' <= ch && ch <= '9')
        {
            x = (x << 3) + (x << 1) + ch - '0';
            ch = getchar();
        }
        return x * f;
    }//快读
    ll head[N],nxt[N],to[N],val[N],fa[N][31],dis[N];
    ll t,n,q,cnt;
    void reset()
    {
        mm(head);
        mm(to);
        mm(val);
        mm(fa);
        mm(dis);
        cnt = 0;
    }
    void add(ll u,ll v)
    {
        cnt++;
        nxt[cnt] = head[u];
        head[u] = cnt;
        to[cnt] = v;
    }
    void dfs(ll u,ll pa)
    {
        for(ll i = 1;i <= 20;i++)
        {
            fa[u][i] = fa[fa[u][i - 1]][i - 1];//预处理出所有的祖先
        }
        for(ll i = head[u];i;i = nxt[i])
        {
            dfs(to[i],u);
        }
    }
    ll f(ll x,ll num)
    {
        for(ll i = 20;i >= 0;i--)
        {
            if(val[fa[x][i]] >= num)
            x = fa[x][i];//倍增往上爬
        }
        return x;
    }
    int main()
    {
        t = read();
        for(int i = 1;i <= t;i++)
        {
            reset();
            val[0] = 1;
            dis[0] = 1;
            n = read();q = read();
            for(ll i = 1;i <= n - 1;i++)
            {
                ll p = read(),s = read();
                add(p,i);
                fa[i][0] = p;
                val[i] = s;
            }
            dfs(0,0);
            printf("Case %d:
    ",i);//这句话非常关键QAQ
            while(q--)
            {
                ll k = read(),v = read();
                printf("%d
    ",f(k,v));
            }
        }
        return 0;
    }
  • 相关阅读:
    【笔记】模电lesson04 晶体管
    [笔记]模电如何判断和识别二极管的正负极
    [笔记]模电用数字万用表判断三极管管脚
    【笔记】模电lesson06 放大电路分析方法I
    【笔记】模电lesson07 放大电路分析方法II
    【翻译】在Verilog设计中使用参数化模块库(Quartus II)(Verilog)
    【原创】DE2实验练习解答—lab5 Clocks and Timers 【Verilog】【Digital Logic】
    【笔记】模电lesson 02 常用半导体器件
    【翻译】modelsim指南 I 之基本仿真(digital logic)
    【原创】DE2 实验练习解答—lab 2:数字和显示(digital Logic)(DE2)
  • 原文地址:https://www.cnblogs.com/lijilai-oi/p/10691617.html
Copyright © 2011-2022 走看看