标签:
http://acm.hdu.edu.cn/showproblem.php?pid=4123
5 5 1 2 3 2 3 4 4 5 3 3 4 2 1 2 3 4 5 0 0
1 3 3 3 5
/** hdu 4123 树形DP+RMQ 题目大意:给定一棵树,每一个点都从当前位置走到距离最远的位置,1~n的连续区间中最大并且走的最远距离差值不超过Q的区间右多大 解题思路:两遍dfs求出在树中到当前点的最长距离:dfs1求出以当前节点为根节点的子树中到该节点的最长距离和次长距离,dfs2将上一步求出的 最长距离和经过根节点的最长距离比较取最大。利用RMQ查询寻找最大区间 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; const int N=50050; int head[N],ip; struct note { int v,w,next; }edge[N*2]; void init() { memset(head,-1,sizeof(head)); ip=0; } void addedge(int u,int v,int w) { edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++; } int maxn[N],smaxn[N],maxid[N],smaxid[N]; 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].v; if(pre==v)continue; dfs1(v,u); if(maxn[v]+edge[i].w>smaxn[u]) { smaxid[u]=v; smaxn[u]=maxn[v]+edge[i].w; if(maxn[u]<smaxn[u]) { 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].v; if(pre==v)continue; if(maxid[u]==v) { if(smaxn[u]+edge[i].w>smaxn[v]) { smaxn[v]=smaxn[u]+edge[i].w; smaxid[v]=u; if(maxn[v]<smaxn[v]) { swap(maxn[v],smaxn[v]); swap(maxid[v],smaxid[v]); } } } else { if(maxn[u]+edge[i].w>smaxn[v]) { smaxn[v]=maxn[u]+edge[i].w; smaxid[v]=u; if(maxn[v]<smaxn[v]) { swap(maxn[v],smaxn[v]); swap(maxid[v],smaxid[v]); } } } dfs2(v,u); } } int a[N],n,m; int dp1[N][30]; int dp2[N][30]; void RMQ_init(int n) { for(int i=1;i<=n;i++) { dp1[i][0]=a[i]; dp2[i][0]=a[i]; } for(int j=1;(1<<j)<=n;j++) { for(int i=1;i+(1<<j)-1<=n;i++)///白书上的模板,次行稍作改动,否则dp数组要扩大一倍防止RE { 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=0; while((1<<(k+1))<=y-x+1)k++; return max(dp1[x][k],dp1[y-(1<<k)+1][k])-min(dp2[x][k],dp2[y-(1<<k)+1][k]); } int main() { while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0)break; init(); for(int i=1;i<n;i++) { int u,v,w; 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]; } RMQ_init(n); while(m--) { int Q; scanf("%d",&Q); int ans=0; int id=1; for(int i=1;i<=n;i++) { while(id<=i&&rmq(id,i)>Q)id++; ans=max(ans,i-id+1); } printf("%d\n",ans); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/46932979