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+尺取法+单调队列)