http://poj.org/problem?id=3162
题意:
一棵n个节点的树。有一个屌丝爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离的差小于M,问怎么取使得天数最多?
思路:
这道题目求最远距离和HDU 2196是一模一样的,这个不是很难。关键是要怎么处理得到的数据。
可以用单调队列做也可以用线段树来做,先介绍一下单调队列。
因为有最大值和最小值,所以我们需要两个单调队列,一个维护最大值,另一个维护最小值。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,ll> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn=1e6+5; 17 18 int n, m; 19 int tot; 20 ll d[maxn][3]; 21 int path[maxn]; 22 int head[2*maxn]; 23 int q_max[maxn]; 24 int q_min[maxn]; 25 26 struct node 27 { 28 int v,w,next; 29 }e[2*maxn]; 30 31 void addEdge(int u,int v,int w) 32 { 33 e[tot].v=v; 34 e[tot].w=w; 35 e[tot].next=head[u]; 36 head[u]=tot++; 37 } 38 39 void dfs1(int u,int fa) 40 { 41 d[u][0]=d[u][1]=0; 42 path[u]=-1; 43 for(int i=head[u];i!=-1;i=e[i].next) 44 { 45 int v=e[i].v; 46 if(v==fa) continue; 47 dfs1(v,u); 48 if(d[u][0]<d[v][0]+e[i].w) 49 { 50 path[u]=v; 51 d[u][1]=d[u][0]; 52 d[u][0]=d[v][0]+e[i].w; 53 } 54 else if(d[u][1]<d[v][0]+e[i].w) 55 d[u][1]=d[v][0]+e[i].w; 56 } 57 } 58 59 void dfs2(int u,int fa) 60 { 61 for(int i=head[u];i!=-1;i=e[i].next) 62 { 63 int v=e[i].v; 64 if(v==fa) continue; 65 if(path[u]==v) d[v][2]=max(d[u][2],d[u][1])+e[i].w; 66 else d[v][2]=max(d[u][0],d[u][2])+e[i].w; 67 dfs2(v,u); 68 } 69 } 70 71 int main() 72 { 73 //freopen("in.txt","r",stdin); 74 while(~scanf("%d%d",&n,&m)) 75 { 76 tot=0; 77 memset(head,-1,sizeof(head)); 78 for(int i=2;i<=n;i++) 79 { 80 int v,w; 81 scanf("%d%d",&v,&w); 82 addEdge(i,v,w); 83 addEdge(v,i,w); 84 } 85 dfs1(1,-1); 86 dfs2(1,-1); 87 int ans=-1; 88 int frt_max=1,rear_max=1; 89 int frt_min=1,rear_min=1; 90 for(int i=1,j=1;i<=n;i++) 91 { 92 d[i][0]=max(d[i][0],d[i][2]); 93 while(frt_max<rear_max && d[q_max[rear_max-1]][0]<d[i][0]) rear_max--; 94 q_max[rear_max++]=i; 95 while(frt_min<rear_min && d[q_min[rear_min-1]][0]>d[i][0]) rear_min--; 96 q_min[rear_min++]=i; 97 98 while(frt_max<rear_max && frt_min<rear_min && d[q_max[frt_max]][0]-d[q_min[frt_min]][0]>m) 99 { 100 if(q_max[frt_max]>q_min[frt_min]) {j=q_min[frt_min]+1;frt_min++;} 101 else {j=q_max[frt_max]+1;frt_max++;} 102 } 103 ans=max(ans,i-j+1); 104 } 105 printf("%d\n",ans); 106 } 107 return 0; 108 }