• bzoj2500: 幸福的道路(树形dp+单调队列)


    好题。。

    先找出每个节点的树上最长路

    由树形DP完成

    节点x,设其最长路的子节点为y

    对于y的最长路,有向上和向下两种情况:

    down:y向子节点的最长路g[y][0]

    up:x的次长路的g[x][1]+dis[x][y]

    up:up[fa[x]]+dis[x][y]

    dfs1找向下,即向子节点的最长路

    dfs2找向上的最长路

    最后最长路f[i]=max(up[x],g[x][0])

    第二部分

    找最长连续子序列,使得序列中abs(mx-mn)<=m

    这次学习了用单调队列的做法

    两个队列mx,mn

    mx存单减的f[i]的i,mn单增

    由于差值不大于m

    每次找出front的最小值出队就行了

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<queue>
     5 #define LL long long
     6 using namespace std;
     7 const int maxn = 1000010;
     8 struct node{
     9     int to,next;
    10     LL cost;
    11 }e[maxn];
    12 int n,m,tot,x;
    13 LL g[maxn][2],f[maxn],y,head[maxn];
    14 
    15 void insert(int u, int v, LL c){
    16     e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].cost=c;
    17 }
    18 
    19 #define v e[i].to
    20 void dfs1(int u){
    21     for (int i=head[u]; i!=-1; i=e[i].next){
    22         dfs1(v);
    23         if (g[u][0]<g[v][0]+e[i].cost){
    24             g[u][1]=max(g[u][1],g[u][0]);
    25             g[u][0]=g[v][0]+e[i].cost;
    26         }else g[u][1]=max(g[u][1],g[v][0]+e[i].cost);
    27     }
    28 }
    29 void dfs2(int u){
    30     for (int i=head[u]; i!=-1; i=e[i].next){
    31         f[v]=f[u]+e[i].cost;
    32         if (g[v][0]+e[i].cost==g[u][0]) f[v]=max(f[v],g[u][1]+e[i].cost);
    33         else f[v]=max(f[v],g[u][0]+e[i].cost);
    34         dfs2(v);
    35     }
    36 }
    37 
    38 int main(){
    39     scanf("%d%d", &n, &m);
    40     tot=1; memset(head,-1,sizeof(head));
    41     for (int i=2; i<=n; i++){
    42         int x; LL y;
    43         scanf("%d%lld", &x, &y);
    44         insert(x,i,y);
    45     }
    46     dfs1(1);
    47     dfs2(1);
    48     for (int i=1; i<=n; i++) f[i]=max(f[i],g[i][0]);
    49     deque<int> mx,mn;
    50     int st=1;
    51     int ans=0;
    52     for (int i=1; i<=n; i++){
    53         while (!mx.empty() && f[mx.back()]<=f[i]) mx.pop_back();
    54         while (!mn.empty() && f[mn.back()]>=f[i]) mn.pop_back();
    55         mx.push_back(i); mn.push_back(i);
    56         while (f[mx.front()]-f[mn.front()]>m){
    57             if (mx.front()<mn.front()){
    58                 st=mx.front()+1;
    59                 mx.pop_front();
    60             }
    61             else{
    62                 st=mn.front()+1;
    63                 mn.pop_front();
    64             }
    65         }
    66         ans=max(ans,i-st+1);
    67     }
    68     printf("%d
    ", ans);
    69     return 0;
    70 }
  • 相关阅读:
    010 排序: 冒泡 选择
    洛谷 P1540 机器翻译
    洛谷 P1011 车站
    周期串
    2019.03.29 大数据图解
    2019.03.29 算法解读
    2019.03.28 博客反省
    2019.03.27 常用的模块
    2019.03.25 git
    2019.03.25 Ajax三级联动
  • 原文地址:https://www.cnblogs.com/mzl0707/p/5766693.html
Copyright © 2020-2023  润新知