poj 3162 Walking Race 树形dp + 单调队列
2017-07-24 21:26
417 查看
题目链接
题意:
给定一棵树,编号为 1 ~ n,
先要求得树上每一点与跟它距离最远的点之间的距离,记为数组 a,
再求得 a 中最长的区间,使得该区间中的元素最大值与最小值的差值不大于给定值 m
其实纯粹是两道题拼起来,
两部分各自的典型例题分别见:
1. hdu 2196 题目链接 blog链接
题意:给定树,求树上每一点与跟它距离最远的点之间的距离
2. hdu 3530 题目链接 blog链接
题意:给定数组,求得最长的区间,使得其中最大值与最小值的差值在给定的范围内(>=m, <=k)
这道题看似复杂,但拆开来,做了上述两道题再写这道题就相对容易了,具体的思路与做法也请参见上面两篇blog
AC代码如下:
题意:
给定一棵树,编号为 1 ~ n,
先要求得树上每一点与跟它距离最远的点之间的距离,记为数组 a,
再求得 a 中最长的区间,使得该区间中的元素最大值与最小值的差值不大于给定值 m
其实纯粹是两道题拼起来,
两部分各自的典型例题分别见:
1. hdu 2196 题目链接 blog链接
题意:给定树,求树上每一点与跟它距离最远的点之间的距离
2. hdu 3530 题目链接 blog链接
题意:给定数组,求得最长的区间,使得其中最大值与最小值的差值在给定的范围内(>=m, <=k)
这道题看似复杂,但拆开来,做了上述两道题再写这道题就相对容易了,具体的思路与做法也请参见上面两篇blog
AC代码如下:
#include <cstdio> #include <iostream> #include <cstring> #define maxn 1000010 using namespace std; typedef long long LL; struct Edge { int from, to, dist, ne; Edge(int a = 0, int b = 0, int c = 0, int d = 0) : from(a), to(b), dist(c), ne(d) {} }edge[maxn * 2]; int next[maxn], tot, adj[maxn], cnt, lo[maxn], hi[maxn]; LL f[maxn][3], g[maxn]; inline LL max(LL a, LL b) { return a > b ? a : b; } void add(int u, int v, int d) { Edge e(u, v, d, next[u]); edge[tot] = e; next[u] = tot++; } void dfs(int u, int fa) { f[u][0] = f[u][1] = 0; for (int i = next[u]; i != -1; i = edge[i].ne) { Edge e = edge[i]; int v = e.to; if (v == fa) continue; dfs(v, u); if (f[v][0] + (LL)e.dist > f[u][0]) { f[u][1] = f[u][0]; f[u][0] = f[v][0] + (LL)e.dist; adj[u] = v; } else if (f[v][0] + (LL)e.dist > f[u][1]) f[u][1] = f[v][0] + (LL)e.dist; } } void dfs2(int u, int fa) { for (int i = next[u]; i != -1; i = edge[i].ne) { Edge e = edge[i]; int v = e.to; if (v == fa) continue; if (adj[u] == v) f[v][2] = f[u][2] > f[u][1] ? f[u][2] : f[u][1]; else f[v][2] = f[u][2] > f[u][0] ? f[u][2] : f[u][0]; f[v][2] += (LL)e.dist; dfs2(v, u); } } int main() { memset(next, -1, sizeof(next)); int n, m; scanf("%d%d", &n, &m); for (int i = 2; i <= n; ++i) { int y, d; scanf("%d%d", &y, &d); add(i, y, d); add(y, i, d); } dfs(1, -1); dfs2(1, -1); // for (int i = 1; i <= n; ++i) printf("%d ", f[i][0]); printf("\n"); // for (int i = 1; i <= n; ++i) printf("%d ", f[i][2]); printf("\n"); for (int i = 1; i <= n; ++i) g[i] = max(f[i][0], f[i][2]); int f1 = 0, r1 = 0, f2 = 0, r2 = 0, l = 1, ans = 1; for (int i = 1; i <= n; ++i) { while (r1 > f1 && g[i] < g[lo[r1 - 1]]) --r1; lo[r1++] = i; while (r2 > f2 && g[i] > g[hi[r2 - 1]]) --r2; hi[r2++] = i; while (g[hi[f2]] - g[lo[f1]] > m) { l = min(hi[f2], lo[f1]) + 1; while (hi[f2] < l) ++f2; while (lo[f1] < l) ++f1; } if (g[hi[f2]] - g[lo[f1]] <= m) ans = max(ans, i - l + 1); } printf("%d\n", ans); // for (int i = 1; i <= n; ++i) printf("%d ", g[i]); printf("\n"); return 0; }
相关文章推荐
- POJ 3162 Walking Race(树形DP + 单调队列)
- POJ 3162 Walking Race(树形dp+单调队列 or 线段树)
- 【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
- POJ 3162 Walking Race(树形DP+单调队列)
- poj 3162 树形dp+单调队列 很好的题
- POJ3162 Walking Race(树形DP+尺取法+单调队列)
- POJ 3162 Walking Race 树形DP
- poj 3162 walking race 树形dp 求符合条件区间
- POJ 3162 - Walking Race(树形DP)
- POJ 3162 Walking Race(树的直径+单调队列)
- poj 3162 Walking Race (dfs+尺取法单调队列)★
- POJ 3162 Walking Race(单调队列或线段树加树型DP)
- poj 3162 树DP+单调队列
- POJ 3162(TreeDP+单调队列)Walking Race
- POJ - 4003 Bob’s Race (树形DP+二分+单调队列+记忆化搜索)@
- POJ 3162 Walking Race (树的直径,单调队列)
- POJ 3162 Walking Race 树的直径加单调队列
- POJ 3162 Walking Race(dfs+单调队列)
- 【树形DP】Poj 3162 Walking Race (DP_树形DP(线段树))
- POJ 3162 Walking Race (单调队列)@