树上倍增问题

城市网络

https://ac.nowcoder.com/acm/problem/13331

原图是这样的
图片说明
当我们 输入 4 2 1 时 我们就是要找 从4 到 2 比 1 大的节点数,我们可以转换成这样的树,红色代表我们新加入的节点,显而易见,4号节点比 1大 , 2号节点比 1大 答案为2

图片说明
那我们就可以转换为把要查询的路径用这样的方式插入,实力太弱的我还是对数据结构掌握不好。~~
我们用f[i][j] 代表当前节点能够买 2^j 个东西的节点是哪个?递推式f[i][j] = f[[f[i][j-1]][j-1] 比如我们从第i个节点买四个东西的话 那么就是 从第i个节点先买2个到达相应的节点再买4个
我们首先确定每个节点第一个比他大的节点是哪个?然后根据递推式确定以后的f数组,再利用dfs进行儿子的类似操作
千万不要忘记每次dfs 后 f 数组都要进行更新
千万不要忘记每次dfs 后 f 数组都要进行更新
千万不要忘记每次dfs 后 f 数组都要进行更新

#include<bits/stdc++.h>
#define pr printf
#define sc scanf
#define fur(i,a,b) for(int i = a; i<= b ;i++)
#define fdr(i,a,b) for(int i = a; i>= b ;i--)
using namespace std;
typedef long long ll;
const int N = 200005;
int a[N],f[N][20],dep[N],to[N],q,n;
vector <int> v[N];
typedef long long ll;
void dfs(int p,int fa)
{
    // p 是 fa 的儿子
    //首先找第一个比p 大的节点
    int x = fa;
    for(int k = 19;  k>=0 ; k--){
        if(f[x][k] && a[f[x][k]] <=a[p])x=f[x][k];
    }
    if(a[x] > a[p]) f[p][0] = x;
    else f[p][0] = f[x][0];
    for(int i = 1 ; i <20 ;i ++)f[p][i] = f[f[p][i-1]][i-1];
    int num = v[p].size();
    dep[p] = dep[fa] + 1 ;
    for(int i = 0 ; i < num ; i ++){
        int y = v[p][i];
        if(y != fa){
            dfs(y,p);
        }
    }
}
int main()
{
   // freopen("in.txt","r",stdin);
    scanf("%d %d",&n,&q);
    for(int i = 1 ; i<= n ;i++)scanf("%d",&a[i]);
    for(int i = 1 ;i <= n - 1 ; i++){
        int x,y;
        scanf("%d %d",&x,&y);
        v[x].push_back(y);
        v[y].push_back(x);
    }
    for(int i = n + 1 ;i <= n + q ; i++){
        int x , y ,c;
        scanf("%d %d %d",&x,&y,&c);
        v[i].push_back(x);
        v[x].push_back(i);
        a[i] = c;
        to[i - n ] = y;
    }
    dfs(1,0);
    for(int i = 1 ; i <= q ; i ++){
        int res = 0 ;
        int x = i + n ;
        for(int k = 19 ; k>=0 ;k --)
        {
            if(dep[f[x][k]]>=dep[to[i]]){
                res += (1<<k);
                x = f[x][k];
            }
        }
        printf("%d\n",res);
    }
    return 0;
}
全部评论
dalao=-=带我
点赞 回复 分享
发布于 2020-04-01 19:55

相关推荐

头像
11-27 14:28
长沙理工大学
刷算法真的是提升代码能力最快的方法吗?&nbsp;刷算法真的是提升代码能力最快的方法吗?
牛牛不会牛泪:看你想提升什么,代码能力太宽泛了,是想提升算法能力还是工程能力? 工程能力做项目找实习,算法也分数据结构算法题和深度学习之类算法
点赞 评论 收藏
分享
10-15 16:27
门头沟学院 C++
LeoMoon:建议问一下是不是你给他付钱😅😅
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-27 10:48
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务