POJ3162 Walking Race(树形DP+尺取法+单调队列)

Posted 新博客↓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3162 Walking Race(树形DP+尺取法+单调队列)相关的知识,希望对你有一定的参考价值。

题目大概是给一棵n个结点边带权的树,记结点i到其他结点最远距离为d[i],问d数组构成的这个序列中满足其中最大值与最小值的差不超过m的连续子序列最长是多长。

各个结点到其他结点的最远距离可以用树形DP解决,HDU2196

而那个最长的连续子序列可以用单调队列求。。搞了挺久看了解法体会了下。。简单来说就是尺取法,用两个指针[i,j]表示区间,j不停+1往前移动,然后用两个单调队列分别同时更新区间最小值和最大值,再看两个队列队首的最值差是否大于m,是的话出队并调整i值,最后用j-i+1更新答案。

当然尺取法+RMQ也是OK的。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define INF (1LL<<60)
 6 #define MAXN 1000111
 7 struct Edge{
 8     int v,w,next;
 9 }edge[MAXN];
10 int NE,head[MAXN];
11 void addEdge(int u,int v,int w){
12     edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u];
13     head[u]=NE++;
14 }
15 int idx[MAXN];
16 long long d[3][MAXN];
17 void dp0(int u){
18     for(int i=head[u]; i!=-1; i=edge[i].next){
19         int v=edge[i].v;
20         dp0(v);
21         if(d[0][u]<=d[0][v]+edge[i].w){
22             d[1][u]=d[0][u];
23             d[0][u]=d[0][v]+edge[i].w;
24             idx[u]=v;
25         }else if(d[1][u]<d[0][v]+edge[i].w){
26             d[1][u]=d[0][v]+edge[i].w;
27         }else if(d[1][u]<d[1][v]+edge[i].w){
28             d[1][u]=d[1][v]+edge[i].w;
29         }
30     }
31 }
32 void dp1(int u){
33     for(int i=head[u]; i!=-1; i=edge[i].next){
34         int v=edge[i].v;
35         if(idx[u]==v) d[2][v]=max(d[1][u],d[2][u])+edge[i].w;
36         else d[2][v]=max(d[0][u],d[2][u])+edge[i].w;
37         dp1(v);
38     }
39 }
40 struct Que{
41     int que[MAXN],front,rear;
42     bool isEmpty(){
43         return front==rear;
44     }
45     int getFront(){
46         return que[front];
47     }
48     int getRear(){
49         return que[rear-1];
50     }
51     void push(int a){
52         que[rear++]=a;
53     }
54 }mxq,mmq;
55 int main(){
56     memset(head,-1,sizeof(head));
57     int n,m,a,b;
58     scanf("%d%d",&n,&m);
59     for(int i=2; i<=n; ++i){
60         scanf("%d%d",&a,&b);
61         addEdge(a,i,b);
62     }
63     dp0(1);
64     dp1(1);
65     int res=0;
66     for(int i=1,j=1; i<=n; ++i){
67         d[0][i]=max(d[0][i],d[2][i]);
68         while(!mxq.isEmpty() && d[0][mxq.getRear()]<d[0][i]) --mxq.rear;
69         mxq.push(i);
70         while(!mmq.isEmpty() && d[0][mmq.getRear()]>d[0][i]) --mmq.rear;
71         mmq.push(i);
72         while(d[0][mxq.getFront()]-d[0][mmq.getFront()]>m){
73             if(mxq.getFront()<mmq.getFront()) j=mxq.getFront()+1,++mxq.front;
74             else j=mmq.getFront()+1,++mmq.front;
75         }
76         res=max(res,i-j+1);
77     }
78     printf("%d",res);
79     return 0;
80 }

 

以上是关于POJ3162 Walking Race(树形DP+尺取法+单调队列)的主要内容,如果未能解决你的问题,请参考以下文章

POJ - 3162 Walking Race 树形dp 单调队列

POJ 3162 Walking Race 树形dp 优先队列

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

POJ3162 Walking Race

poj3162(树形dp+线段树求最大最小值)

hdu 4123--Bob’s Race(树形DP+RMQ)