码迷,mamicode.com
首页 > 其他好文 > 详细

[POJ3162]Walking Race(DP + 单调队列)

时间:2017-06-18 20:42:34      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:show   memset   sdi   题意   技术分享   getchar   set   else   i++   

传送门

 

题意:一棵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 + 单调队列)

标签:show   memset   sdi   题意   技术分享   getchar   set   else   i++   

原文地址:http://www.cnblogs.com/zhenghaotian/p/7045133.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!