zoukankan      html  css  js  c++  java
  • 幸福的道路

    Description

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

    Input

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

    Output

    最长的连续锻炼天数
    

    Solution

    首先我们要把点权求出来。 
    那么我们设1为根节点,用两个数组fir[i]和sec[i]维护从节点i开始最长的路径和次长的路径。 
    第一次先求出起点为i终点在i的子树内的最长路和次长路,第二次再求出每个节点往其父节点走的最长路径。 
    接着就要求最大的区间,这里我一开始的想法是用数据结构来维护,set或者线段树什么的应该都行,但是我们注意到n<=1000000,则这么干有可能会超时。 
    那么我们就改用单调栈来维护最大值和最小值。 
    第一个单调栈保证里面的元素严格递增,第二个单调栈保证里面的元素严格递减,那么最大值就是第二个单调栈的栈底,最小值就是第一个单调栈的栈顶,我们只需要每次插入i时同时维护这两个单调栈即可。
    

    Code

    type
      arr=record
            y,w,next:longint;
          end;
      arrr=record
             num,len:longint;
           end;
    var
      nm,n,m,ans:longint;
      a:array [0..2000001] of arr;
      fir,sec,st1,st2:array [0..1000001] of arrr;
      l,r:array [1..2] of longint;
      ls:array [0..1000001] of longint;
    function max(o,p:longint):longint;
    begin
      if o>p then exit(o);
      exit(p);
    end;
    
    procedure add(u,v,z:longint);
    begin
      inc(nm);
      with a[nm] do
        begin
          y:=v; w:=z;
          next:=ls[u];
          ls[u]:=nm;
        end;
    end;
    
    procedure dfs1(x,fa:longint);
    var
      i:longint;
    begin
      i:=ls[x];
      while i<>0 do
        with a[i] do
          begin
            if y=fa then
              begin
                i:=next;
                continue;
              end;
            dfs1(y,x);
            if fir[y].len+w>fir[x].len then
              begin
                sec[x]:=fir[x];
                fir[x].len:=fir[y].len+w;
                fir[x].num:=y;
              end else
              if fir[y].len+w>sec[x].len then
                begin
                  sec[x].len:=fir[y].len+w;
                  sec[x].num:=y;
                end;
          i:=next;
        end;
    end;
    
    procedure dfs2(x,fa,len:longint);
    var
      i,t:longint;
    begin
      if fir[fa].num=x then t:=sec[fa].len+len
                       else t:=fir[fa].len+len;
      if t>fir[x].len then
        begin
          sec[x]:=fir[x];
          fir[x].len:=t;
          fir[x].num:=fa;
        end else
        if t>sec[x].len then
          begin
            sec[x].len:=t;
            sec[x].num:=fa;
          end;
      i:=ls[x];
      while i<>0 do
        with a[i] do
          begin
            if y=fa then
              begin
                i:=next;
                continue;
              end;
            dfs2(y,x,w);
            i:=next;
          end;
    end;
    
    procedure init;
    var
      i,x,y:longint;
    begin
      fillchar(ls,sizeof(ls),0);
      readln(n,m); nm:=0;
      for i:=2 to n do
        begin
          readln(x,y);
          add(x,i,y);
          add(i,x,y);
        end;
    end;
    
    procedure main;
    var
      i,ll,t:longint;
    begin
      l[1]:=1; l[2]:=1; r[1]:=0; r[2]:=0;
      ans:=0; ll:=1;
      for i:=1 to n do
        begin
          t:=fir[i].len;
          while (l[1]<=r[1]) and (st1[r[1]].len>=t) do
            dec(r[1]);
          inc(r[1]);
          st1[r[1]].len:=t;
          st1[r[1]].num:=i;
          while (l[2]<=r[2]) and (st2[r[2]].len<=t) do
            dec(r[2]);
          inc(r[2]);
          st2[r[2]].len:=t;
          st2[r[2]].num:=i;
            while st2[l[2]].len-st1[l[1]].len>m do
              if st1[l[1]].num<st2[l[2]].num then
                begin
                  ll:=st1[l[1]].num+1;
                  inc(l[1]);
                end else
                begin
                  ll:=st2[l[2]].num+1;
                  inc(l[2]);
                end;
            ans:=max(ans,i-ll+1);
        end;
    end;
    
    begin
      init;
      dfs1(1,0);
      dfs2(1,0,0);
      main;
      write(ans);
    end.
    
  • 相关阅读:
    matlab简单线性规划&单纯形法
    matlab多变量绘图函数(类似ggplot2)
    matlab近似泛函优化
    如何求矩阵的逆矩阵
    数值分析手写笔记
    latex绘图小结
    数理统计手写笔记
    matlab kriging模型
    运筹学与最优化手写笔记
    matlab既约梯度法习题
  • 原文地址:https://www.cnblogs.com/zyx-crying/p/9319535.html
Copyright © 2011-2022 走看看