[POJ3162]Walking Race(DP + 单调队列)
Posted 蒟蒻zht的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POJ3162]Walking Race(DP + 单调队列)相关的知识,希望对你有一定的参考价值。
题意:一棵n个节点的树。wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离的差小于M,问怎么取使得天数最多?
求每个点到最远距离的点的距离可以用 computer 的方法。
至于第二问,可以跑一遍2个单调队列。
具体是固定左端点,右端点向右平移到最远,直到不能平移,再左端点向右平移一位。在这中间维护单调队列和更新 ans 最大值。
具体细节看代码
——代码
#include <cstdio> #include <cstring> #include <iostream> #define N 1000001 #define max(x, y) ((x) > (y) ? (x) : (y)) int n, m, cnt, h1 = 1, t1, h2 = 1, t2, ans; int head[N], to[N << 1], val[N << 1], next[N << 1], f[N][3], a[N], q1[N], q2[N]; bool vis[N]; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == \'-\') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - \'0\'; return x * f; } inline void add(int x, int y, int z) { to[cnt] = y; val[cnt] = z; next[cnt] = head[x]; head[x] = cnt++; } inline void dfs1(int u) { int i, v, d1 = 0, d2 = 0; vis[u] = 1; for(i = head[u]; i ^ -1; i = next[i]) { v = to[i]; if(!vis[v]) { dfs1(v); if(f[v][0] + val[i] > d1) d2 = d1, d1 = f[v][0] + val[i]; else if(f[v][0] + val[i] > d2) d2 = f[v][0] + val[i]; } } f[u][0] = d1; f[u][1] = d2; } inline void dfs2(int u) { int i, v; vis[u] = 1; for(i = head[u]; i ^ -1; i = next[i]) { v = to[i]; if(!vis[v]) { if(f[v][0] + val[i] == f[u][0]) f[v][2] = f[u][1] + val[i]; else f[v][2] = f[u][0] + val[i]; f[v][2] = max(f[v][2], f[u][2] + val[i]); dfs2(v); } } } int main() { int i, x, y, z; while(~scanf("%d %d", &n, &m)) { ans = cnt = 0; memset(f, 0, sizeof(f)); memset(head, -1, sizeof(head)); for(i = 1; i < n; i++) { x = read(); y = read(); add(i + 1, x, y); add(x, i + 1, y); } memset(vis, 0, sizeof(vis)); dfs1(1); memset(vis, 0, sizeof(vis)); dfs2(1); for(i = 1; i <= n; i++) a[i] = max(f[i][0], f[i][2]); for(x = 1, y = 0; x <= n; x++) { while(q1[h1] < x && h1 <= t1) h1++; while(q2[h2] < x && h2 <= t2) h2++; while(a[q1[h1]] - a[q2[h2]] < m && y <= n) { y++; while(a[q1[t1]] < a[y] && h1 <= t1) t1--; q1[++t1] = y; while(a[q2[t2]] > a[y] && h2 <= t2) t2--; q2[++t2] = y; } ans = max(ans, y - x); } printf("%d\\n", ans); } return 0; }
以上是关于[POJ3162]Walking Race(DP + 单调队列)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3162 Walking Race 树形dp 优先队列
POJ3162 Walking Race(树形DP+尺取法+单调队列)