• 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 }
  • 相关阅读:
    同时实现同时只允许一个人登录系统 dodo
    比较C#中的readonly与const (转) dodo
    iframe,Frame中关于Session丢失的解决方法 dodo
    sqlserver数据库同步解决方案 dodo
    利用C#调用WINRAR实现压缩与解压 dodo
    .net打包自动安装数据库 dodo
    关于sqlserver packet size dodo
    真正生成高质量不变形缩略图片 dodo
    Datagrid列表控件使用 dodo
    NUnit学习之VS.net 2005篇(转) dodo
  • 原文地址:https://www.cnblogs.com/WABoss/p/5312349.html
Copyright © 2020-2023  润新知