hdu 4123 Bob’s Race(树形dp+RMQ)

题目链接:hdu 4123 Bob’s Race

题目大意:一个城镇有N个住户,N-1条路连接两个住户,保证N个住户联通,M次询问,给定N条边的信息,包括连

接的住户序号以及路的长度。然后是M次询问,每次询问Q,要求找到最长的连续序号,使得Max(dis[i]) - Min(dis[i]) ≤

Q(l≤i≤r),输出最大的r-l+1。dis[i]为从第i个住户出发,不重复走过路能移动的最远距离。

解题思路:树形dp,通过两次dfs,第1次处理出每个节点中孩子节点移动的最长距离和第二长距离,第2次考虑从父

亲节点过来的路径,维护每个节点的最长距离即可。

然后用RMQ与处理加快询问速度,枚举右边界确定左边界,单次复杂度为o(n).

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 50005;

int N, M, E, Q, first[maxn], jump[maxn * 2], dpMax[maxn][20], dpMin[maxn][20];
struct Edge {
    int u, v, w;
    void set(int u, int v, int w) {
        this->u = u;
        this->v = v;
        this->w = w;
    }
}ed[maxn * 2];

inline void add_Edge (int u, int v, int w) {
    ed[E].set(u, v, w);
    jump[E] = first[u];
    first[u] = E++;
}

int fmax[maxn], fidx[maxn], smax[maxn], sidx[maxn];

inline void maintain(int u, int w, int v) {
    if (w > smax[u]) {
        smax[u] = w;
        sidx[u] = v;
    }

    if (smax[u] > fmax[u]) {
        swap(smax[u], fmax[u]);
        swap(sidx[u], fidx[u]);
    }
}

void dfs(int u, int pre) {
    fmax[u] = fidx[u] = smax[u] = sidx[u] = 0;
    for (int i = first[u]; i + 1; i = jump[i]) {
        int v = ed[i].v;
        if (v == pre)
            continue;
        dfs(v, u);
        maintain(u, fmax[v] + ed[i].w, v);
    }
}

void dfs(int u, int pre, int d) {
    maintain(u, d, pre);
    for (int i = first[u]; i + 1; i = jump[i]) {
        int v = ed[i].v;
        if (v == pre)
            continue;
        dfs(v, u, (v == fidx[u] ? smax[u] : fmax[u]) + ed[i].w);
    }
}

void rmq_init() {
    for (int i = 1; i <= N; i++)
        dpMax[i][0] = dpMin[i][0] = fmax[i];

    for (int k = 1; (1<<k) <= N; k++) {
        for (int i = 1; i + (1<<k) - 1 <= N; i++) {
            dpMax[i][k] = max(dpMax[i][k-1], dpMax[i+(1<<(k-1))][k-1]);
            dpMin[i][k] = min(dpMin[i][k-1], dpMin[i+(1<<(k-1))][k-1]);
        }
    }
}

int rmq_query(int l, int r) {
    int k = 0;
    while ((1<<(k+1)) <= r - l + 1) k++;
    return max(dpMax[l][k], dpMax[r-(1<<k)+1][k]) - min(dpMin[l][k], dpMin[r-(1<<k)+1][k]);
}

int main () {
    while (scanf("%d%d", &N, &M) == 2 && N + M) {
        int u, v, w;
        E = 0;
        memset(first, -1, sizeof(first));
        for (int i = 1; i < N; i++) {
            scanf("%d%d%d", &u, &v, &w);
            add_Edge(u, v, w);
            add_Edge(v, u, w);
        }

        dfs(1, 0);
        dfs(1, 0, 0);

        rmq_init();
        while (M--) {
            int ans = 0, mv = 1;
            scanf("%d", &Q);
            for (int i = 1; i <= N; i++) {
                while (mv <= i && rmq_query(mv , i) > Q) mv++;
                ans = max(ans, i - mv + 1);
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}
时间: 2024-10-13 09:07:35

hdu 4123 Bob’s Race(树形dp+RMQ)的相关文章

hdu 4123 Bob’s Race (树的直径相关+rmq+单调队列思想)

Bob's Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2115    Accepted Submission(s): 658 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble

HDU 4123 Bob&#39;s Race:单调队列 + st表

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123 题意: 给你一棵树,n个节点,每条边有长度. 然后有m个询问,每个询问给定一个q值. 设dis[i]为:从节点i出发,不重复经过节点,所能够走的最远距离. 每次询问问你:区间[l,r]最长能有多长,同时保证 max{dis[i]} - min{dis[i]} <= q (i∈[l,r]) 题解: 首先有一个结论: 从树上的任意一个节点出发,尽可能往远走,最终一定会到达树的直径的两个端点之一.

hdu 4123 Bob’s Race 树的直径+rmq+尺取

Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads

HDU 4123 Bob’s Race

Bob’s Race Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4123 Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads

HDU 4123 Bob’s Race(RMQ)

题意是说给出一棵树,N(10^5)个顶点,以及每条边的权值,现在需要选择连续的K个点(顶点编号连续),可以被选出来的条件是: 若d[i]代表顶点i到树上其他点的距离的最大值,使得区间[a, b]的d值的最大差值不大于Q, 也就是max(d[a], d[a + 1], ..., d[b]) - max(d[a], d[a + 1], ..., d[b]) <= Q Q是给出的一个查询(共有m<=500个查询),求对应每一个查询的K的最大值 思路是首先预处理出每个点到其他点的最大距离, 这可以通过

HDU 4123 Bob’s Race 树的直径+单调队列

题意: 给定n个点的带边权树Q个询问. 下面n-1行给出树 下面Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列使得序列中最大值-最小值 <= u,输出这个序列的长度. 思路: 求dp数组就是求个树的直径然后dfs一下. 对于每个询问,可以用一个单调队列维护一下.O(n)的回答. #include <cstdio> #include <cstring> #include <strin

hdu 4123 树形DP+RMQ

http://acm.hdu.edu.cn/showproblem.php?pid=4123 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses,

Bestcoder round #65 &amp;&amp; hdu 5593 ZYB&#39;s Tree 树形dp

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 354    Accepted Submission(s): 100 Problem Description ZYB has a tree with N nodes,now he wants you to solve the numbers of nodes distanced no m

hdu 4514 并查集+树形dp

湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 4539    Accepted Submission(s): 816 Problem Description 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,