[Uma pergunta por dia] Em 31 de março, o título do tópico dobrou na árvore

Link do título

Rede da cidade

Tópico:

Prática: Observe que o título afirma que v é o lca de u e v.

Então só precisamos multiplicar a árvore, f [i] [j] representa o ponto em que o nó i sobe 2 ^ j e é maior que o atual

Como é o peso de entrada, preciso adicionar um novo ponto a todos os pontos que preciso perguntar, mesmo sob u, o peso do novo ponto é o peso inicial da consulta, ele pode ser dobrado a partir desse novo ponto. .

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
vector<int>G[N];
int n,q;
int val[N],f[N][23],to[N],dep[N];
void dfs(int u,int fa)
{
    dep[u] = dep[fa] + 1;
    int x = fa;
    for(int i = 22; i >= 0; --i){
        if(f[x][i] && val[f[x][i]] <= val[u]) x = f[x][i];//找到第一个u节点小的点
    }


    if(val[x] > val[u]) f[u][0] = x;
    else f[u][0] = f[x][0];

    for(int i = 1; i <= 22; ++i) f[u][i] = f[f[u][i-1]][i-1];

    for(int v:G[u]){
        if(v == fa) continue;
        dfs(v,u);
    }

}
int main()
{
    cin>>n>>q;

    for(int i = 1; i <= n; ++i) scanf("%d",&val[i]);

    for(int i = 1; i < n; ++i) {
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for(int i = n + 1; i <= n + q ; ++i){//增加新点
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        G[i].push_back(u);
        G[u].push_back(i);
        val[i] = w;
        to[i - n] = v;
    }
    dfs(1,0);

    //printf("f[6]:%d %d\n",f[6][1],f[f[6][0]][0]);

    for(int i = 1; i <= q; ++i){
        int x = i + n;
        int ans = 0;
        for(int k = 22; k >= 0; --k){
            if(dep[f[x][k]] >= dep[to[i]]) {
                //printf("x:%d k:%d f:%d\n",x,k,f[x][k]);
                ans += (1 << k),x = f[x][k];
            }
        }
        printf("%d\n",ans);
    }
    return 0;

}

 

Publicado 519 artigos originais · elogiou 69 · 50.000+ visualizações

Acho que você gosta

Origin blog.csdn.net/qq_41286356/article/details/105221228
Recomendado
Clasificación