POJ 3162 Walking Race(树形dp+单调队列 or 线段树)

http://poj.org/problem?id=3162

题意:
一棵n个节点的树。有一个屌丝爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离的差小于M,问怎么取使得天数最多?

 

思路:
这道题目求最远距离和HDU 2196是一模一样的,这个不是很难。关键是要怎么处理得到的数据。

可以用单调队列做也可以用线段树来做,先介绍一下单调队列。

因为有最大值和最小值,所以我们需要两个单调队列,一个维护最大值,另一个维护最小值。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<sstream>
  6 #include<vector>
  7 #include<stack>
  8 #include<queue>
  9 #include<cmath>
 10 #include<map>
 11 #include<set>
 12 using namespace std;
 13 typedef long long ll;
 14 typedef pair<int,ll> pll;
 15 const int INF = 0x3f3f3f3f;
 16 const int maxn=1e6+5;
 17 
 18 int n, m;
 19 int tot;
 20 ll d[maxn][3];
 21 int path[maxn];
 22 int head[2*maxn];
 23 int q_max[maxn];
 24 int q_min[maxn];
 25 
 26 struct node
 27 {
 28     int v,w,next;
 29 }e[2*maxn];
 30 
 31 void addEdge(int u,int v,int w)
 32 {
 33     e[tot].v=v;
 34     e[tot].w=w;
 35     e[tot].next=head[u];
 36     head[u]=tot++;
 37 }
 38 
 39 void dfs1(int u,int fa)
 40 {
 41     d[u][0]=d[u][1]=0;
 42     path[u]=-1;
 43     for(int i=head[u];i!=-1;i=e[i].next)
 44     {
 45         int v=e[i].v;
 46         if(v==fa)  continue;
 47         dfs1(v,u);
 48         if(d[u][0]<d[v][0]+e[i].w)
 49         {
 50             path[u]=v;
 51             d[u][1]=d[u][0];
 52             d[u][0]=d[v][0]+e[i].w;
 53         }
 54         else if(d[u][1]<d[v][0]+e[i].w)
 55             d[u][1]=d[v][0]+e[i].w;
 56     }
 57 }
 58 
 59 void dfs2(int u,int fa)
 60 {
 61     for(int i=head[u];i!=-1;i=e[i].next)
 62     {
 63         int v=e[i].v;
 64         if(v==fa)  continue;
 65         if(path[u]==v)  d[v][2]=max(d[u][2],d[u][1])+e[i].w;
 66         else  d[v][2]=max(d[u][0],d[u][2])+e[i].w;
 67         dfs2(v,u);
 68     }
 69 }
 70 
 71 int main()
 72 {
 73     //freopen("in.txt","r",stdin);
 74     while(~scanf("%d%d",&n,&m))
 75     {
 76         tot=0;
 77         memset(head,-1,sizeof(head));
 78         for(int i=2;i<=n;i++)
 79         {
 80             int v,w;
 81             scanf("%d%d",&v,&w);
 82             addEdge(i,v,w);
 83             addEdge(v,i,w);
 84         }
 85         dfs1(1,-1);
 86         dfs2(1,-1);
 87         int ans=-1;
 88         int frt_max=1,rear_max=1;
 89         int frt_min=1,rear_min=1;
 90         for(int i=1,j=1;i<=n;i++)
 91         {
 92             d[i][0]=max(d[i][0],d[i][2]);
 93             while(frt_max<rear_max && d[q_max[rear_max-1]][0]<d[i][0])  rear_max--;
 94             q_max[rear_max++]=i;
 95             while(frt_min<rear_min && d[q_min[rear_min-1]][0]>d[i][0])  rear_min--;
 96             q_min[rear_min++]=i;
 97 
 98             while(frt_max<rear_max && frt_min<rear_min && d[q_max[frt_max]][0]-d[q_min[frt_min]][0]>m)
 99             {
100                 if(q_max[frt_max]>q_min[frt_min])   {j=q_min[frt_min]+1;frt_min++;}
101                 else {j=q_max[frt_max]+1;frt_max++;}
102             }
103             ans=max(ans,i-j+1);
104         }
105         printf("%d\n",ans);
106     }
107     return 0;
108 }
单调队列
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<sstream>
  6 #include<vector>
  7 #include<stack>
  8 #include<queue>
  9 #include<cmath>
 10 #include<map>
 11 #include<set>
 12 using namespace std;
 13 typedef long long ll;
 14 typedef pair<int,ll> pll;
 15 const int INF = 0x3f3f3f3f;
 16 const int maxn=1e6+5;
 17 
 18 int n, m;
 19 int tot;
 20 ll d[maxn][3];
 21 int path[maxn];
 22 int head[2*maxn];
 23 
 24 int MAX[maxn<<2];
 25 int MIN[maxn<<2];
 26 int query_max,query_min;
 27 
 28 struct node
 29 {
 30     int v,w,next;
 31 }e[2*maxn];
 32 
 33 void addEdge(int u,int v,int w)
 34 {
 35     e[tot].v=v;
 36     e[tot].w=w;
 37     e[tot].next=head[u];
 38     head[u]=tot++;
 39 }
 40 
 41 /**********************************************
 42 dfs
 43 **********************************************/
 44 
 45 void dfs1(int u,int fa)
 46 {
 47     d[u][0]=d[u][1]=0;
 48     path[u]=-1;
 49     for(int i=head[u];i!=-1;i=e[i].next)
 50     {
 51         int v=e[i].v;
 52         if(v==fa)  continue;
 53         dfs1(v,u);
 54         if(d[u][0]<d[v][0]+e[i].w)
 55         {
 56             path[u]=v;
 57             d[u][1]=d[u][0];
 58             d[u][0]=d[v][0]+e[i].w;
 59         }
 60         else if(d[u][1]<d[v][0]+e[i].w)
 61             d[u][1]=d[v][0]+e[i].w;
 62     }
 63 }
 64 
 65 void dfs2(int u,int fa)
 66 {
 67     for(int i=head[u];i!=-1;i=e[i].next)
 68     {
 69         int v=e[i].v;
 70         if(v==fa)  continue;
 71         if(path[u]==v)  d[v][2]=max(d[u][2],d[u][1])+e[i].w;
 72         else  d[v][2]=max(d[u][0],d[u][2])+e[i].w;
 73         dfs2(v,u);
 74     }
 75 }
 76 
 77 /**********************************************
 78 线段树
 79 **********************************************/
 80 
 81 void PushUp(int o)
 82 {
 83     MAX[o]=max(MAX[o<<1],MAX[o<<1|1]);
 84     MIN[o]=min(MIN[o<<1],MIN[o<<1|1]);
 85 }
 86 
 87 void build(int l, int r, int o)
 88 {
 89     if(l==r)
 90     {
 91         MAX[o]=MIN[o]=max(d[l][0],d[l][2]);
 92         return;
 93     }
 94     int mid=(l+r)/2;
 95     build(l,mid,o<<1);
 96     build(mid+1,r,o<<1|1);
 97     PushUp(o);
 98 }
 99 
100 void query(int ql, int qr, int l, int r, int o)
101 {
102     if(ql<=l && qr>=r)
103     {
104         query_max=max(query_max,MAX[o]);
105         query_min=min(query_min,MIN[o]);
106         return;
107     }
108     int mid=(l+r)/2;
109     if(ql<=mid)  query(ql,qr,l,mid,o<<1);
110     if(mid<qr)   query(ql,qr,mid+1,r,o<<1|1);
111 }
112 
113 int main()
114 {
115     //freopen("in.txt","r",stdin);
116     while(~scanf("%d%d",&n,&m))
117     {
118         tot=0;
119         memset(head,-1,sizeof(head));
120         for(int i=2;i<=n;i++)
121         {
122             int v,w;
123             scanf("%d%d",&v,&w);
124             addEdge(i,v,w);
125             addEdge(v,i,w);
126         }
127         dfs1(1,-1);
128         dfs2(1,-1);
129         build(1,n,1);
130         int ans=0;
131 
132         int l=1,r=1;
133         while(r<=n)
134         {
135             query_max=0; query_min=INF;
136             query(l,r,1,n,1);
137             if(query_max-query_min<=m)  {ans=max(ans,r-l+1);r++;}
138             while(query_max-query_min>m)
139             {
140                 l++;
141                 query_max=0; query_min=INF;
142                 query(l,r,1,n,1);
143             }
144         }
145         printf("%d\n",ans);
146     }
147     return 0;
148 }
线段树

 

posted @ 2017-08-12 10:37  Kayden_Cheung  阅读(458)  评论(0编辑  收藏  举报
//目录