牛客每日一题3.31 城市网络 树上倍增

https://blog.csdn.net/qq_43804974/article/details/105196280

数据修复后,之前的就T掉了~还是树上倍增,dp[i][j]就是节点i开始拿了2^j个物品后所在的位置,递推就是dp[i][j] = dp[dp[i][j-1]][j - 1];然后只要倍增得到dp[i][0]就可以了。对每个询问新建立节点,这样找答案就很方便,而且也不会出现错误答案,因为新建立的节点必定是叶子节点,所以不会对其他答案造成影响。还有就是倍增的时候可以利用lg[深度]去稍稍优化一下,下面代码跑了181ms

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<time.h>
#include<string>
#include<cmath>
#include<stack>
#include<map>
#include<set>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define ll long long
#define double long double
using namespace std;
#define PI  3.1415926535898
#define eqs 1e-17
const long long max_ = 1e6 + 7;
int mod = 2014;
const int inf = 1e9 + 7;
const long long INF = 1e18;
int read() {
    int s = 0, f = 1;
    char ch = getchar();
    while (ch<'0' || ch>'9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0'&&ch <= '9') {
        s = s * 10 + ch - '0';
        ch = getchar();
    }
    return s * f;
}
inline void write(int x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
inline int min(int a, int b) {
    return a < b ? a : b;
}
inline int max(int a, int b) {
    return a > b ? a : b;
}
int n, m, s, head[max_], xiann = 1, cnt = 1, deepth[max_], lg[max_], father[max_][50];
int dp[max_][50],node[max_];
struct k {
    int next, to;
}xian[max_];
inline void add_(int a, int b) {
    xian[xiann].next = head[a];
    xian[xiann].to = b;
    head[a] = xiann;
    xiann++;
}

void dfs(int now, int fa) {
    if (now == 4 || now == 7) {
        int t = 1;
    }
    deepth[now] = deepth[fa] + 1;
    if (node[now] < node[fa]) {
        dp[now][0] = fa;
    }
    else {

        int x = fa;
        for (register int i = lg[deepth[fa]] + 1; i >= 0; i--) {
            if (dp[x][i] && node[dp[x][i]] <= node[now])x = dp[x][i];
        }
        dp[now][0] = dp[x][0];
    }
    for (register int i = 1; i <= lg[deepth[now]] + 1; i++) {
        dp[now][i] = dp[dp[now][i - 1]][i - 1];
    }
    for (int i = head[now]; i; i = xian[i].next) {
        int to = xian[i].to;
        if (to != fa) {
            dfs(to, now);
        }
    }
}
int aim[max_];
signed main() {
    lg[0] = -1;
    n = read(); m = read(); 
    //lg是向下取整的 
    for (register int i = 1; i <= n + m + 1; i++) {
        lg[i] = lg[i >> 1] + 1;
    }
    for (int i = 1; i <= n; i++)node[i] = read();
    for (register int i = 1; i <= n - 1; i++) {
        int a = read(), b = read();
        add_(a, b);
        add_(b, a);
    }
    for (int i = 1; i <= m; i++) {
        int now = read(), to = read(), v = read();
        node[n + i] = v;
        aim[i] = to;
        add_(n + i, now);
        add_(now, n + i);
    }
    dfs(1, 0);
    for (int j = 1; j <= m; j++) {
        int now = j + n, to = aim[j];
        int ans = 0;
        for (register int i = lg[deepth[now]] + 1; i >= 0; i--) {
            if (dp[now][i] && deepth[to] <= deepth[dp[now][i]]) {
                ans += (1 << i); now = dp[now][i];
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
全部评论

相关推荐

11-18 09:44
Java
小白也想要offer:简历别放洋屁,搞不还还放错了,当然你投外企除外,以上纯属个人观点
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务