1128 - Greatest Parent---LightOj(LCA+离线算法)

题目链接: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:\n", t++);
        for(int i=1; i<=q; i++)
            printf("%d\n", ans[i]);
    }
    return 0;
}

时间: 2024-10-17 13:28:41

1128 - Greatest Parent---LightOj(LCA+离线算法)的相关文章

HDU 2874 LCA离线算法

Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4477    Accepted Submission(s): 1284 Problem Description After World War X, a lot of cities have been seriously damage

HDU 2874 Connections between cities(LCA离线算法实现)

http://acm.hdu.edu.cn/showproblem.php?pid=2874 题意: 求两个城市之间的距离. 思路: LCA题,注意原图可能不连通. 如果不了解离线算法的话,可以看我之前博客写的解释http://www.cnblogs.com/zyb993963526/p/7295894.html 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cs

LCA离线算法Tarjan详解

离线算法也就是需要先把所有查询给保存下来,最后一次输出结果. 离线算法是基于并查集实现的,首先就是初始化P[i] = i. 接下来对于每个点进行dfs: ①首先判断是否有与该点有关的查询,如果当前该点为u,与它有关的点为v,如果v已经访问过了,那么它们的LCA就是find(v).如果v还没有访问,那就不用管它. ②对该点的子节点继续dfs,需要注意的是,dfs完之后需要需要p[v]=u,将v点并到其父亲节点上. 1 void LCA(int u) 2 { 3 vis[u]=1; 4 for(in

Closest Common Ancestors---poj1470(LCA+离线算法)

题目链接:http://poj.org/problem?id=1470 题意是给出一颗树,q个查询,每个查询都是求出u和v的LCA:    以下是寻找LCA的预处理过程: void LCA(u){ for(u的每个儿子v) { LCA(v); union(u,v);//并到一个集合中去 } visit[u]=1; for(查询中u的每个儿子v) { if(visit[v]) u,v的最近公共祖先是father[getfather(v)]; } } 详细解释   图文详解  本题可以使用预处理的方

HDU 2586 LCA离线算法 tarjan算法

LCA tarjan算法模板题 题意:给一个无根树,有q个询问,每个询问两个点,问两点的距离. 用tarjan离线算法算出每个询问的两点的最近公共祖先 ans[i]=dis[x[i]]+dis[y[i]]-2*dis[z[i]]; //  x[i],y[i]分别存储每次询问的两点,z[i]存储这两点的最近公共祖先 #include "stdio.h" #include "string.h" int tot,n,m; int f[40010],x[40010],y[4

[LightOJ 1128]Greatest Parent

原题链接:http://www.lightoj.com/volume_showproblem.php?problem=1128 原题是英文题面,大概翻译了一下: 最大的祖先 树是一个连通的无环图,在这个问题中给出一个有根树,每个点有一个权值,每个点的权值严格的大于它父亲的权值.现在给出一个点以及一个整数的询问,你需要找到这个点最大的可能的祖先(也许可能包括这个点),它的权值大于或等于给出的整数. 输入 输入的开始是一个整数 T (T≤ 5), 表示测试数据的数量. 每一个情况的第一行是一个空行,

HDU 2874 LCA离线算法 tarjan算法

给出N个点,M条边,Q次询问 Q次询问每两点之间的最短距离 典型LCA 问题   Marjan算法解 #include "stdio.h" #include "string.h" struct Edge { int to,next,len; }edge[20010]; struct Ques { int to,next,index; }ques[2000010]; int head[10010],q_head[10010],f[10010],dis[10010];

笔记:LCA最近公共祖先 Tarjan(离线)算法

LCA最近公共祖先 Tarjan他贱(离线)算法的基本思路及其算法实现 本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig/article/details/52336496 https://baike.baidu.com/item/最近公共祖先/8918834?fr=aladdin 最近公共祖先简称LCA(Lowest Common Ancesto

POJ 1330 Nearest Common Ancestors 【最近公共祖先LCA算法+Tarjan离线算法】

Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20715   Accepted: 10910 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figure, each