POJ 3162 Walking Race 树形dp 优先队列

Posted 鲸头鹳

tags:

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

题意 :  一棵n个节点的树。wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离的差小于M,问怎么取使得天数最多?

 
每个点的最大距离和之前http://acm.hdu.edu.cn/showproblem.php?pid=2196这道题一样
(就是求每个子树的最长子链,次长子链,然后求经过父亲节点能达到的最大值,比较一下)
 
嗯求最长连续天数这个显然n^2是不现实的,但是连续什么的会想起很久以前似曾相识的一道优先队列题...然后强行一个大根堆一个小根堆,l和r适当情况下右移,复杂度n就可以a了...
技术分享
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<queue>
  7 using namespace std;
  8 #define pa pair<long long,int>
  9 const int maxn=1000010;
 10 int n,m;
 11 priority_queue< pa,vector< pa >,less< pa > >q1;
 12 priority_queue< pa,vector< pa >,greater< pa > >q2;
 13 struct nod{
 14     int y;
 15     long long v;
 16     int next;
 17 }e[maxn*2];
 18 int vis[maxn]={};
 19 long long f[maxn][3]={}; //0父亲 1最长 2次长
 20 long long ma[maxn]={};
 21 int f1[maxn][3]={};
 22 int head[maxn]={};
 23 int tot=0;
 24 void init(int x,int y,long long v){
 25     e[++tot].y=y;
 26     e[tot].v=v;
 27     e[tot].next=head[x];
 28     head[x]=tot;
 29 }
 30 void dfs(int x){
 31     int y;
 32     vis[x]=1;
 33     long long tmp=0;
 34     for(int i=head[x];i;i=e[i].next){
 35         y=e[i].y;
 36         tmp=e[i].v;
 37         if(!vis[y]){
 38             dfs(y);
 39             tmp+=f[y][1];
 40             if(tmp>f[x][1]){
 41                 f[x][2]=f[x][1];
 42                 f1[x][2]=f1[x][1];
 43                 f[x][1]=tmp;
 44                 f1[x][1]=y;
 45             }
 46             else if(tmp>f[x][2]){
 47                 f[x][2]=tmp;
 48                 f1[x][2]=y;
 49             }
 50         }
 51     }
 52 }
 53 void dfs2(int x,int fa,long long v){
 54     int y;
 55     long long tmp;
 56     vis[x]=1;
 57     if(f1[fa][1]==x){
 58         f[x][0]=v+max(f[fa][0],f[fa][2]);
 59     }
 60     else{
 61         f[x][0]=v+max(f[fa][0],f[fa][1]);
 62     }
 63     ma[x]=max(f[x][0],f[x][1]);
 64     for(int i=head[x];i;i=e[i].next){
 65         y=e[i].y;
 66         tmp=e[i].v;
 67         if(!vis[y]){
 68             dfs2(y,x,tmp);
 69         }
 70     }
 71 }
 72 long long mab(long long x){
 73     if(x<0){
 74         return -x;
 75     }
 76     return x;
 77 }
 78 int main(){
 79     scanf("%d%d",&n,&m);
 80     int y;
 81     long long v;
 82     for(int i=1;i<n;i++){
 83         scanf("%d%lld",&y,&v);
 84         init(i+1,y,v);
 85         init(y,i+1,v);
 86     }dfs(1);
 87     memset(vis,0,sizeof(vis));
 88     dfs2(1,0,0);
 89     int ans=0;
 90     int l=1,r=0;
 91     for(int i=1;i<=n;i++){
 92         q1.push(make_pair(ma[i],i));
 93         q2.push(make_pair(ma[i],i));
 94         r++;
 95         int id1=q1.top().second,id2=q2.top().second;
 96         while(id1<l){
 97             q1.pop();
 98             id1=q1.top().second;
 99         }
100         while(id2<l){
101             q2.pop();
102             id2=q2.top().second;
103         }
104         long long z1=q1.top().first,z2=q2.top().first;
105         while(mab(z1-z2)>=m){
106             l++;
107             while(id1<l){
108                 q1.pop();
109                 id1=q1.top().second;
110             }
111             while(id2<l){
112                 q2.pop();
113                 id2=q2.top().second;
114             }
115             z1=q1.top().first,z2=q2.top().first;
116         }ans=max(ans,r-l+1);
117     }
118     cout<<ans<<endl;
119     return 0;
120 }
View Code

 

以上是关于POJ 3162 Walking Race 树形dp 优先队列的主要内容,如果未能解决你的问题,请参考以下文章

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

POJ 3162 Walking Race 树形dp 优先队列

POJ3162 Walking Race

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

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

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