Greatest Parents Ligh OJ1128

其實倍增可以”縮”

題意:

一棵樹的點權會給你,每一次詢問一個x,y 問在x的祖先之中(包括x) 權值 >=y的而且是離x最遠的點的編號!

思路

核心的什麼也不說了,只是希望說一說這個:
每一次倍增,dp[i][j]~dp[i][0]其實就是相當於是一個二分搜索的過程呢!
比如dp[i][3]會符合答案,那麼i就會自動”跳”到 i+2^3的地方,繼續在(i+2^3)的地方2^2
一直下去,於是就有了答案!

代碼:

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define N 100005
#define M 20
using namespace std;
int T, n, m, x, y, val[N]={1}, fa[N][M], dp[N][M];
vector<int> G[N];
void DFS(int now)
{
    for (int i = 0; i < G[now].size(); i++)
    {
        int v = G[now][i];
        fa[v][0] = now, dp[v][0] = val[v];
        for (int j = 1; j < M; j++)
            fa[v][j] = fa[fa[v][j - 1]][j - 1];
        for (int j = 1; j < M; j++)
            dp[v][j] = max(dp[v][j - 1], dp[fa[v][j - 1]][j - 1]);
        DFS(v);
    }
}
inline int solve(int x, int y)
{
    for (int i = M-1; i >= 0; i--)
        if (dp[fa[x][i]][i] >= y)
            x = fa[x][i];
    return x;
}
int main()
{
    scanf("%d", &T);
    for (int loc = 1; loc <= T; loc++)
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i <= n; i++)
            G[i].clear(), fa[0][i] = 0, dp[0][i] = 1;
        for (int i = 1; i < n; i++)
        {
            scanf("%d%d", &x, &val[i]);
            G[x].push_back(i);
        }
        DFS(0);
        printf("Case %d:\n", loc);
        for (int i = 1; i <= m; i++)
        {
            scanf("%d%d", &x, &y);
            printf("%d\n", solve(x, y));
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章