• 1128


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

    给你一颗树,树的每个节点都有一个权值,树根是节点0,权值为1,树中每个节点的权值都是大于父节点的权值的;

    然后给出每个节点的父节点以及该节点的权值;有Q个询问,每个询问有两个数u和val,求u的祖先中权值>=val的最大祖先,就是离u最远的那个>=val的祖先的节点;

    数的范围较大有5w个Q,1w个n,所以我们不能直接模拟,也许这1w个节点是一串下来的,那么复杂度就变成了nQ必定会TLE;

    我们知道每个节点i要找祖先中>=val的一定要从根节点到i的路径上去找,所以我们可以用二分;具体看代码吧;

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <stack>
    #include <math.h>
    
    using namespace std;
    
    #define met(a, b) memset(a, b, sizeof(a))
    #define N 100053
    #define INF 0x3f3f3f3f
    const int MOD = 1e9+7;
    
    typedef long long LL;
    
    struct node
    {
        int Index, val;
        node(){}
        node(int Index, int val) : Index(Index), val(val){}
    };
    
    int v[N], n, ans[N], Time, Node[N];
    vector<vector<int> >G;
    vector<vector<node> >Q;
    
    int Find(int val)
    {
        int L = 1, R = Time, ans = Time;
        while(L<=R)
        {
            int Mid = (L+R)/2;
            if(v[Node[Mid]] >= val)
            {
                R = Mid-1;
                ans = Mid;
            }
            else
                L = Mid+1;
        }
        return Node[ans];
    }
    
    void dfs(int u)
    {
        Node[++Time] = u;///Node[i]表示从根节点0到节点i的深度;
    
        int len = Q[u].size();///在询问中 问u节点的我们可以从根节点到u节点这个路径上寻找v大于val的节点,用二分法;
        for(int i=0; i<len; i++)
        {
            node p = Q[u][i];
            ans[p.Index] = Find(p.val);///把结果保存起来;
        }
    
        for(int i=0, L=G[u].size(); i<L; i++)
            dfs(G[u][i]);
    
        Time--;///返回上一层,深度要减;
    }
    
    int main()
    {
        int T, q, t = 1;
        scanf("%d", &T);
        while(T--)
        {
            met(v, 0);
            v[0] = 1;
    
            scanf("%d %d", &n, &q);
    
            G.clear();
            G.resize(n+5);
    
            Q.clear();
            Q.resize(n+5);
    
            int f, u, num;
            for(int i=1; i<n; i++)
            {
                scanf("%d %d", &f, &v[i]);
                G[f].push_back(i);
            }
            for(int i=1; i<=q; i++)
            {
                scanf("%d %d", &u, &num);
                Q[u].push_back(node(i, num));
            }
    
            Time = 0;
            dfs(0);
    
            printf("Case %d:
    ", t++);
            for(int i=1; i<=q; i++)
                printf("%d
    ", ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    GYM 101572C(模拟)
    GYM 101572A(单调队列优化dp)
    Codeforces 183C(有向图上的环长度)
    Codeforces 183A(坐标系性质)
    2019湘潭校赛 G(并查集)
    2019湘潭校赛 H(dp)
    2019湘潭校赛 E(答案区间维护)
    Codeforces 1141F2(贪心、预处理)
    Codeforces Round #411(Div. 2)——ABCDEF
    基数排序学习
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5743478.html
Copyright © 2020-2023  润新知