1. 程式人生 > >[POJ3162]Walking Race(DP + 單調隊列)

[POJ3162]Walking Race(DP + 單調隊列)

sed 固定 code aot .org view span put 開始

傳送門

題意:一棵n個節點的樹。wc愛跑步,跑n天,第i天從第i個節點開始跑步,每次跑到距第i個節點最遠的那個節點(產生了n個距離),現在要在這n個距離裏取連續的若幹天,使得這些天裏最大距離和最小距離的差小於M,問怎麽取使得天數最多?

求每個點到最遠距離的點的距離可以用 computer 的方法。

至於第二問,可以跑一遍2個單調隊列。

具體是固定左端點,右端點向右平移到最遠,直到不能平移,再左端點向右平移一位。在這中間維護單調隊列和更新 ans 最大值。

具體細節看代碼

——代碼

技術分享
  1 #include <cstdio>
  2
#include <cstring> 3 #include <iostream> 4 #define N 1000001 5 #define max(x, y) ((x) > (y) ? (x) : (y)) 6 7 int n, m, cnt, h1 = 1, t1, h2 = 1, t2, ans; 8 int head[N], to[N << 1], val[N << 1], next[N << 1], f[N][3], a[N], q1[N], q2[N]; 9 bool vis[N];
10 11 inline int read() 12 { 13 int x = 0, f = 1; 14 char ch = getchar(); 15 for(; !isdigit(ch); ch = getchar()) if(ch == -) f = -1; 16 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - 0; 17 return x * f; 18 } 19 20 inline void add(int
x, int y, int z) 21 { 22 to[cnt] = y; 23 val[cnt] = z; 24 next[cnt] = head[x]; 25 head[x] = cnt++; 26 } 27 28 inline void dfs1(int u) 29 { 30 int i, v, d1 = 0, d2 = 0; 31 vis[u] = 1; 32 for(i = head[u]; i ^ -1; i = next[i]) 33 { 34 v = to[i]; 35 if(!vis[v]) 36 { 37 dfs1(v); 38 if(f[v][0] + val[i] > d1) d2 = d1, d1 = f[v][0] + val[i]; 39 else if(f[v][0] + val[i] > d2) d2 = f[v][0] + val[i]; 40 } 41 } 42 f[u][0] = d1; 43 f[u][1] = d2; 44 } 45 46 inline void dfs2(int u) 47 { 48 int i, v; 49 vis[u] = 1; 50 for(i = head[u]; i ^ -1; i = next[i]) 51 { 52 v = to[i]; 53 if(!vis[v]) 54 { 55 if(f[v][0] + val[i] == f[u][0]) f[v][2] = f[u][1] + val[i]; 56 else f[v][2] = f[u][0] + val[i]; 57 f[v][2] = max(f[v][2], f[u][2] + val[i]); 58 dfs2(v); 59 } 60 } 61 } 62 63 int main() 64 { 65 int i, x, y, z; 66 while(~scanf("%d %d", &n, &m)) 67 { 68 ans = cnt = 0; 69 memset(f, 0, sizeof(f)); 70 memset(head, -1, sizeof(head)); 71 for(i = 1; i < n; i++) 72 { 73 x = read(); 74 y = read(); 75 add(i + 1, x, y); 76 add(x, i + 1, y); 77 } 78 memset(vis, 0, sizeof(vis)); 79 dfs1(1); 80 memset(vis, 0, sizeof(vis)); 81 dfs2(1); 82 for(i = 1; i <= n; i++) a[i] = max(f[i][0], f[i][2]); 83 for(x = 1, y = 0; x <= n; x++) 84 { 85 while(q1[h1] < x && h1 <= t1) h1++; 86 while(q2[h2] < x && h2 <= t2) h2++; 87 while(a[q1[h1]] - a[q2[h2]] < m && y <= n) 88 { 89 y++; 90 while(a[q1[t1]] < a[y] && h1 <= t1) t1--; 91 q1[++t1] = y; 92 while(a[q2[t2]] > a[y] && h2 <= t2) t2--; 93 q2[++t2] = y; 94 } 95 ans = max(ans, y - x); 96 } 97 printf("%d\n", ans); 98 } 99 return 0; 100 }
View Code

[POJ3162]Walking Race(DP + 單調隊列)