• 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 }
  • 相关阅读:
    JS和C#对Json的操作
    JS图形化插件利器组件系列 —— Gojs组件
    Android APK反编译 apktool使用教程
    UML系列图
    多线程学习 ---- 系列教程
    大型网站架构之系列
    经典算法题锦集
    基本算法系列15天速成
    居转户--相关信息
    使用C#创建Windows服务
  • 原文地址:https://www.cnblogs.com/wsy01/p/8111369.html
Copyright © 2020-2023  润新知