Description
Input
Output
Sample Input
5 5 1 2 3 2 3 4 4 5 3 3 4 2 1 2 3 4 5 0 0
Sample Output
1 3 3 3 5题意:有n村庄,简称点,n-1条边,每条边有一个长度,在k个连续的村庄有k个人参加比赛(k是所要求得),每个人都向边缘跑,跑的越远越好,每个人跑的最远距离记为Di;然后有Q个询问,每次给出距离差d,在连续的k个村庄中k个人的Di之差不能超过d,求最大的k,我们先求出每个点能跑的最远距离,然后用ST 的RMQ算法计算区间Di的最大值与最小值,最大值与最小值之差小于d那么k个人的Di之差全部小于d,然后用尺取法找最大连续区间,就是我们要求的k:在这个题中有三的知识点,1,求每个点可达的最远距离;2,RMQ求区间最值;3,尺取求出最大区间k;在本题中不一一讲解每个知识点,代码中有一些关于知识点1的介绍#include <iostream> #include <stdio.h> #include <string.h> #include <vector> using namespace std; const int Maxn=50050; struct Edge { int to,cap,next; }edge[Maxn*2]; int head[Maxn],tot; void init() { tot=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w) { edge[tot].to=v; edge[tot].cap=w; edge[tot].next=head[u]; head[u]=tot++; } int maxn[Maxn];///距离叶子最远; int smaxn[Maxn];///相反方向 距离叶子最远的 int maxid[Maxn]; ///指向 走向最远 的方向 int smaxid[Maxn];///与 “指向 走向最远 的方向”这个方向相反的方向 void dfs1(int u,int pre) { maxn[u]=smaxn[u]=maxid[u]=smaxid[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre)continue; dfs1(v,u);///深入到树叶然后向上递归 if(maxn[v]+edge[i].cap>smaxn[u]) { ///此时此刻maxn[v]+edge[i].cap就是maxn[u],但是不管三七二十一了,最后交换去吧 smaxn[u]=maxn[v]+edge[i].cap; smaxid[u]=v; if(maxn[u]<smaxn[u])///最后总会交换maxn 和 smaxn,所以每次更新smaxn好了 { swap(maxn[u],smaxn[u]);///交换值 swap(maxid[u],smaxid[u]);///方向也交换 } } } } void dfs2(int u,int pre) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre)continue; if(maxid[u]==v)///u->v 向长的一端跑 { if(smaxn[u] + edge[i].cap > smaxn[v])///更新下一个节点短向的值 { smaxn[v] = smaxn[u] + edge[i].cap; smaxid[v] = u; if(maxn[v] < smaxn[v]) { swap(maxn[v],smaxn[v]); swap(maxid[v],smaxid[v]); } } } else ///反向 向短的一端跑 { if(maxn[u] + edge[i].cap > maxn[v]) { maxn[v] = maxn[u] + edge[i].cap; maxid[v] = u; if(maxn[v] < smaxn[v]) { swap(maxn[v],smaxn[v]); swap(maxid[v],smaxid[v]); } } } dfs2(v,u); } } int a[Maxn]; int dp1[Maxn][20]; int dp2[Maxn][20]; int mm[Maxn]; void initRMQ(int n) { mm[0] = -1; for(int i = 1;i <= n;i++) { mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1]; dp1[i][0] = a[i]; dp2[i][0] = a[i]; } for(int j = 1;j <= mm[n];j++) for(int i = 1;i + (1<<j) - 1 <= n;i++) { dp1[i][j] = max(dp1[i][j-1],dp1[i + (1<<(j-1))][j-1]); dp2[i][j] = min(dp2[i][j-1],dp2[i + (1<<(j-1))][j-1]); } } int rmq(int x,int y) { int k = mm[y-x+1]; return //min(dp2[x][k],dp2[y-(1<<k)+1][k]); max(dp1[x][k],dp1[y-(1<<k)+1][k])- min(dp2[x][k],dp2[y-(1<<k)+1][k]); } int main() { int n,m; int u,v,w,q; while(scanf("%d%d",&n,&m)!=-1) { if(n==0) break; init(); for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } dfs1(1,1); dfs2(1,1); for(int i=1;i<=n;i++) a[i]=maxn[i]; initRMQ(n); for(int i=0;i<m;i++) { scanf("%d",&q); int ans=0,id=1; for(int i=1;i<=n;i++) { while(id<=i&&rmq(id,i)>q) { id++; cout<<rmq(id,i)<<endl; } ans=max(ans,i-id+1); } printf("%d\n",ans); } } return 0; }