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
题意:
给你一棵树。定义一个结点到其它结点的最大长度为该点的路径长度。现给你一个q值。问你最多有多少个标号连续的结点满足。其中路径的最大值和最小值之差不超过q。
思路:
先树形DP求出一个结点的路径值。然后RMQ维护区间的最大最小值。然后l,r指针扫描区间就行了。比赛时就该写的。可是因为卡题了。所以就没写的机会了。
详细见代码:
#include<algorithm> #include<iostream> #include<string.h> #include<sstream> #include<stdio.h> #include<math.h> #include<vector> #include<string> #include<queue> #include<set> #include<map> using namespace std; const int INF=0x3f3f3f3f; const int maxn=100010; struct node { int v,md,len; node *next; }edge[maxn<<1],*head[maxn]; int dp[maxn],cnt,n,m; int vis[maxn],lg[maxn],rmqb[25][maxn],rmqs[25][maxn]; void init() { cnt=0; memset(vis,0,sizeof vis); memset(head,0,sizeof head); } void pre_rmq() { int i; lg[0]=-1; for(i=1;i<maxn;i++) lg[i]=lg[i>>1]+1; } void rmq_init() { int i,j; for(i=1;i<=n;i++) rmqb[0][i]=rmqs[0][i]=dp[i]; for(i=1;i<=lg[n];i++) for(j=1;j+(1<<i)-1<=n;j++) { rmqb[i][j]=max(rmqb[i-1][j],rmqb[i-1][j+(1<<(i-1))]); rmqs[i][j]=min(rmqs[i-1][j],rmqs[i-1][j+(1<<(i-1))]); } } int rmq_max(int l,int r) { int tmp=lg[r-l+1]; return max(rmqb[tmp][l],rmqb[tmp][r-(1<<tmp)+1]); } int rmq_min(int l,int r) { int tmp=lg[r-l+1]; return min(rmqs[tmp][l],rmqs[tmp][r-(1<<tmp)+1]); } void adde(int u,int v,int l) { edge[cnt].v=v; edge[cnt].len=l; edge[cnt].next=head[u]; head[u]=&edge[cnt++]; } void dfs(int fa,int u) { int v; node *p; dp[u]=0; for(p=head[u];p!=NULL;p=p->next) { v=p->v; if(v==fa) continue; dfs(u,v); p->md=dp[v]+p->len; dp[u]=max(dp[u],dp[v]+p->len); } } void getdis(int u,int v) { if(vis[v]) return ; vis[v]=1; node *p; int md=0; for(p=head[u];p!=NULL;p=p->next) { if(p->v!=v) md=max(md,p->md); } for(p=head[v];p!=NULL;p=p->next) if(p->v==u) { p->md=md+p->len; dp[v]=max(dp[v],p->md); } for(p=head[v];p!=NULL;p=p->next) getdis(v,p->v); } void predis() { node *p; dfs(1,1); vis[1]=1; for(p=head[1];p!=NULL;p=p->next) getdis(1,p->v); } int main() { int x,y,z,q,i,l,r,ans; //freopen("in.txt","r",stdin); pre_rmq(); while(scanf("%d%d",&n,&m),n||m) { init(); for(i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); adde(x,y,z); adde(y,x,z); } predis(); rmq_init(); //for(i=1;i<=n;i++) // printf("dis %d %d\n",i,dp[i]); for(i=0;i<m;i++) { ans=1; scanf("%d",&q); l=r=1; while(r<=n) { if(rmq_max(l,r)-rmq_min(l,r)<=q) { ans=max(ans,r-l+1); r++; } else l++; } printf("%d\n",ans); } } return 0; }