bzoj2500幸福的道路 树形dp+单调队列

Posted wsy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2500幸福的道路 树形dp+单调队列相关的知识,希望对你有一定的参考价值。

2500: 幸福的道路

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 434  Solved: 170
[Submit][Status][Discuss]

Description

 
小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光.
他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图.
他们不愿枯燥的每天从同一个地方开始他们的锻炼,所以他们准备给起点标号后顺序地从每个起点开始(第一天从起点一开始,第二天从起点二开始……). 而且他们给每条道路定上一个幸福的值.很显然他们每次出发都想走幸福值和最长的路线(即从起点到树上的某一点路径中最长的一条).
他们不愿再经历之前的大起大落,所以决定连续几天的幸福值波动不能超过M(即一段连续的区间并且区间的最大值最小值之差不超过M).他们想知道要是这样的话他们最多能连续锻炼多少天(hint:不一定从第一天一直开始连续锻炼)?
现在,他们把这个艰巨的任务交给你了!

Input

第一行包含两个整数N, M(M<=10^9).
第二至第N行,每行两个数字Fi , Di, 第i行表示第i个节点的父亲是Fi,且道路的幸福值是Di.

Output

最长的连续锻炼天数

Sample Input

3 2
1 1
1 3

Sample Output

3
数据范围:
50%的数据N<=1000
80%的数据N<=100 000
100%的数据N<=1000 000

 

这其实是两个题强行合在一起啊。。
首先是对于每个节点求它在树上的最长路,可以树形dp 2次,一次从儿子转移一次从父亲转移
求最长连续区间的话维护两个单调队列max min就好

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define N 1000005
 6 #define ll long long
 7 using namespace std;
 8 int n,m,tot,w[N],hd[N],ans=1;
 9 ll f[N],g[N],a[N];int mx[N],mn[N];
10 struct edge{int v,w,next;}e[N<<1];
11 char gc(){
12     static char s[1000000],*p1,*p2;
13     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
14     if(p1==p2)return EOF;
15     return *p1++; 
16 }
17 int read(){
18     int x=0;char ch=gc();
19     while(ch>9||ch<0)ch=gc();
20     while(ch<=9&&ch>=0)x=x*10+ch-0,ch=gc();
21     return x; 
22 }
23 void adde(int u,int v,int w){
24     e[++tot].v=v;
25     e[tot].next=hd[u];
26     e[tot].w=w;
27     hd[u]=tot; 
28 }
29 void dfs1(int u,int fa){
30      for(int i=hd[u];i;i=e[i].next){
31          int v=e[i].v;
32          if(v==fa)continue;
33          dfs1(v,u);
34          f[u]=max(f[u],f[v]+e[i].w); 
35      }
36 }
37 void dfs2(int u,int fa){
38     ll mx1=0,mx2=0;
39     for(int i=hd[u];i;i=e[i].next){
40         int v=e[i].v;if(v==fa)continue;
41         if(f[v]+e[i].w>mx1)mx2=mx1,mx1=f[v]+e[i].w;
42         else if(f[v]+e[i].w>mx2)mx2=f[v]+e[i].w;
43         g[v]=g[u]+e[i].w;
44     }
45     for(int i=hd[u];i;i=e[i].next){
46         int v=e[i].v;if(v==fa)continue;
47         if(f[v]+e[i].w==mx1)g[v]=max(g[v],mx2+e[i].w);
48         else if(mx1+e[i].w>g[v])g[v]=mx1+e[i].w;
49         dfs2(v,u); 
50     }
51 }
52 void solve(){
53     for(register int i=1;i<=n;i++)a[i]=max(g[i],f[i]);
54     int l1=1,l2=1,r2=0,r1=0,t=1;
55     for(register int i=1;i<=n;i++){
56         while(l1<=r1&&a[i]>=a[mx[r1]])r1--;
57         while(l2<=r2&&a[i]<=a[mn[r2]])r2--;
58         mx[++r1]=i;mn[++r2]=i;
59         while(a[mx[l1]]-a[mn[l2]]>m){
60             if(mx[l1]<=mn[l2])t=mx[l1]+1,l1++;
61             else t=mn[l2]+1,l2++;
62         }
63         ans=max(ans,i-t+1);
64     }
65 }
66 int main(){
67      n=read();m=read();
68      for(register int i=2;i<=n;i++){
69          int v=read(),w=read();
70          adde(i,v,w);adde(v,i,w);
71      }dfs1(1,0);dfs2(1,0);
72      solve();printf("%d",ans);
73      return 0;
74 }

 

以上是关于bzoj2500幸福的道路 树形dp+单调队列的主要内容,如果未能解决你的问题,请参考以下文章

●BZOJ 2500 幸福的道路

BZOJ2282[Sdoi2011]消防 树形DP+双指针法+单调队列

BZOJ 2500 幸福的道路

[树形dp][Tarjan][单调队列] Bzoj 1023 cactus仙人掌图

BZOJ 2500 幸福的道路(race) 树上直径+平衡树

BZOJ-2435道路修建 (树形DP?)DFS