POJ3162 Walking Race

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3162 Walking Race相关的知识,希望对你有一定的参考价值。

题解:

分为两部分,第一部分和SGU149一样。

第二个部分:给你一个数组,求最长的连续的一段子数组,使得该子数组中的最大值减去最小值不超过M

学到了新姿势。。。用2个单调队列去维护,o(n)时间就行了

具体的可以去看POJ上面的discuss。。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
#define pb push_back
#define mp make_pair
#define se second
#define fs first
#define LL long long
#define CLR(x) memset(x,0,sizeof x)
#define MC(x,y) memcpy(x,y,sizeof(x))  
#define SZ(x) ((int)(x).size())
#define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 
typedef pair<int,int> P;
const double eps=1e-9;
const int N=1e6+10;
const int M=1e3+10;
const LL mod=1000000007;
const int INF=1e9+10;

int n,m,cnt;
int head[N];
int down1[N],down2[N],up[N],Son[N],ans[N];
int qmax[N],qmin[N];
struct Edge{
    int v,w,nxt;
}edge[N*2];

void Init(){
    cnt=0;
    memset(head,-1,sizeof(head));
    memset(up,0,sizeof(up));
}

void AddEdge(int u,int v,int w){
    edge[cnt].v=v;
    edge[cnt].nxt=head[u];
    edge[cnt].w=w;
    head[u]=cnt++;
}


void dfs1(int u,int fa){
    down1[u]=down2[u]=0;
    for(int i=head[u];i!=-1;i=edge[i].nxt){
        int v=edge[i].v;
        int w=edge[i].w;
        if(v==fa) continue;
        dfs1(v,u);
        down2[u]=max(down2[u],down1[v]+w);
        if(down2[u]>down1[u]){
            swap(down2[u],down1[u]);
            Son[u]=v;
        }
    }
}

void dfs2(int u,int fa){
    for(int i=head[u];i!=-1;i=edge[i].nxt){
        int v=edge[i].v;
        int w=edge[i].w;
        if(v==fa) continue;
        if(Son[u]!=v) up[v]=max(up[u],down1[u])+w;
        else          up[v]=max(up[u],down2[u])+w;
        dfs2(v,u);
    }
}

void solve(){
    int goal=0,i,j;
    int f1,r1,f2,r2;
    f1=r1=f2=r2=0;
    for(i=1,j=1;j<=n;j++){
        while(r1>f1&&ans[qmax[r1-1]]<=ans[j]) r1--;
        qmax[r1++]=j;
        while(r2>f2&&ans[qmin[r2-1]]>=ans[j]) r2--;
        qmin[r2++]=j;
        if(ans[qmax[f1]]-ans[qmin[f2]]>m){
            goal=max(goal,j-i);
            while(ans[qmax[f1]]-ans[qmin[f2]]>m){
                i=min(qmax[f1],qmin[f2])+1;
                while(r1>f1&&qmax[f1]<i) f1++;
                while(r2>f2&&qmin[f2]<i) f2++;
            }
        }
    }
    goal=max(goal,j-i);
    printf("%d\n",goal);
}


int main(){
     scanf("%d%d",&n,&m);
     Init();
     for(int i=1;i<n;i++){
         int x,y;
         scanf("%d%d",&x,&y);
         AddEdge(x,i+1,y);AddEdge(i+1,x,y);
     }
     dfs1(1,-1);
     dfs2(1,-1);
     for(int i=1;i<=n;i++) ans[i]=max(down1[i],up[i]);
     solve();
     return 0;
}

 

以上是关于POJ3162 Walking Race的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3162 Walking Race 树形dp 优先队列

POJ - 3162 Walking Race 树形dp 单调队列

POJ3162 Walking Race(树形DP+尺取法+单调队列)

[POJ3162]Walking Race(DP + 单调队列)

poj3162(树形dp+线段树求最大最小值)

POJ - 2110 - Mountain Walking(二分/bfs)