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 }
以上是关于POJ 3162 Walking Race 树形dp 优先队列的主要内容,如果未能解决你的问题,请参考以下文章
POJ - 3162 Walking Race 树形dp 单调队列
POJ 3162 Walking Race 树形dp 优先队列