HDU 4213 Bob’s Race(树形dp+单调队列)

来源:互联网 发布:视频教学软件 编辑:程序博客网 时间:2024/05/18 01:28

题目链接:
HDU 4213 Bob’s Race
题意:
给出一个n个节点的树,先对每个点求最远可到的距离,然后有m询问,每次询问找一个最长的区间使得区间的距离最值差小于等于limit,输出区间长度。
数据范围:n5104,m500,5000,limit107
分析:
首先两遍dfs处理出每个点可到达的最远距离。之前写过:Here。
然后就可以单调队列处理了,之前也写过:There。
Good luck….

#include <stdio.h>#include <string.h>#include <algorithm>#include <math.h>using namespace std;typedef long long ll;const int MAX_N = 50010;int n, m, total;int head[MAX_N], down[MAX_N], ddown[MAX_N], id[MAX_N], father[MAX_N], best[MAX_N];int inc[MAX_N], dec[MAX_N], inc_head, inc_tail, dec_head, dec_tail;struct Edge {    int v, w, next;}edge[MAX_N * 2];void AddEdge(int u, int v, int w){    edge[total].v = v;    edge[total].w = w;    edge[total].next = head[u];    head[u] = total++;}void dfs_son(int u, int p){    for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].v, w = edge[i].w;        if (v == p) continue;        dfs_son(v, u);         if (w + down[v] > down[u]) {            ddown[u] = down[u];            down[u] = down[v] + w;            id[u] = v;         } else if (down[v] + w > ddown[u]) {            ddown[u] = down[v] + w;         }    }}void dfs_father(int u, int p){    for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].v, w = edge[i].w;        if (v == p) continue;        if (id[u] == v) father[v] = max(father[u], ddown[u]) + w;        else father[v] = max(father[u], down[u]) + w;        dfs_father(v, u);    }   }int main(){    while (~scanf("%d%d", &n, &m) && (n || m)) {        memset(head, -1, sizeof(head));        total = 0;        for (int i = 1; i < n; ++i) {            int u, v, w;            scanf("%d%d%d", &u, &v, &w);            AddEdge(u, v, w);            AddEdge(v, u, w);        }           memset(down, 0, sizeof(down));        memset(ddown, 0, sizeof(ddown));        memset(id, -1, sizeof(id));        dfs_son(1, 0);        dfs_father(1, 0);        for (int i = 1; i <= n; ++i) { best[i] = max(down[i], father[i]); }        for (int i = 0; i < m; ++i) {            int limit, ans = 0, pre = 1;            scanf("%d", &limit);            inc_head = inc_tail = dec_head = dec_tail = 1;            for (int j = 1; j <= n; ++j) {                while (inc_tail > inc_head && best[inc[inc_tail - 1]] > best[j]) inc_tail--;                inc[inc_tail++] = j;                while (dec_tail > dec_head && best[dec[dec_tail - 1]] < best[j]) dec_tail--;                dec[dec_tail++] = j;                while (1) {                    int diff = best[dec[dec_head]] - best[inc[inc_head]];                    if (diff <= limit) break;                    if (dec[dec_head] < inc[inc_head]) {                        pre = dec[dec_head] + 1;                        dec_head++;                    } else {                        pre = inc[inc_head] + 1;                        inc_head++;                    }                }                ans = max(ans, j - pre + 1);            }            printf("%d\n", ans);        }    }    return 0;}
0 0
原创粉丝点击