hdu 4123 Bob’s Race(树形DP+rmq)

题目链接:hdu 4123 Bob’s Race

题意:

给你n个节点,n-1条边的树,每条边有一个边权,定义dis[i]为距离i这个点最远的距离。

现在有m个询问,每个询问给一个q,然后找一段节点标号连续的点,使得max(dis[j])-min(dis[i])<=q;

问最长的一段区间。

题解:

最开始还以为这个连续指的是有边相连,然后感觉无法做啊,然后百度了一下,发现是标号的相连。

先求出每一个点的dis,如果不会,请先做hdu 2196 Computer(树形DP)

因为m比较小,我们就可以考虑对每个询问用双指针滚一下。

然后双指针滚的时候要求每段区间的最大值和最小值,所以这里用rmq预处理一下最大和最小值,

或者也可以用单调队列维护一下  都行。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4 const int N=5e4+7;
 5 int n,m,g[N],v[2*N],nxt[N*2],w[N*2],ed,dis[N],en,mx,mxx[N][20],mii[N][20];
 6 
 7 void adg(int x,int y,int z){v[++ed]=y,w[ed]=z,nxt[ed]=g[x],g[x]=ed;}
 8 
 9 void dfs(int x,int fa,int dep)
10 {
11     dis[x]=max(dis[x],dep);
12     if(dep>mx)mx=dep,en=x;
13     for(int i=g[x];i;i=nxt[i])
14         if(v[i]!=fa)dfs(v[i],x,dep+w[i]);
15 }
16 
17 void rmq(int *a,int f[][20],int k)
18 {
19     F(i,1,n)f[i][0]=a[i];
20     for(int j=1;1<<j<n;j++)F(i,1,n)
21     if(i+(1<<j)-1<= n)
22     f[i][j]=k?max(f[i][j-1],f[i+(1<<j-1)][j-1]):min(f[i][j-1],f[i+(1<<j-1)][j-1]);
23     else break;
24 }
25 inline int find(int l,int r,int v)
26 {
27     int k=31-__builtin_clz(r-l+1);
28     return v?max(mxx[l][k],mxx[r-(1<<k)+1][k]):min(mii[l][k],mii[r-(1<<k)+1][k]);
29 }
30 
31 int find(int x)
32 {
33     int l=1,r=0,ans=0,mxx=0,mii=-N;
34     while(r<n)
35     {
36         while(r<n&&(l>r||find(l,r+1,1)-find(l,r+1,0)<=x))r++;
37         ans=max(ans,r-l+1),r++;
38         if(r>n)break;
39         while(l<r&&find(l,r,1)-find(l,r,0)>x)l++;
40         ans=max(ans,r-l+1);
41     }
42     return ans;
43 }
44 
45 int main()
46 {
47     while(scanf("%d%d",&n,&m),n+m)
48     {
49         memset(g,0,sizeof(g)),ed=mx=0;
50         int x,y,z;
51         F(i,1,n-1)
52         {
53             scanf("%d%d%d",&x,&y,&z);
54             adg(x,y,z),adg(y,x,z);
55         }
56         F(i,1,n)dis[i]=0;
57         dfs(1,0,0),dfs(en,0,0),dfs(en,0,0);
58         rmq(dis,mxx,1),rmq(dis,mii,0);
59         while(m--)
60         {
61             scanf("%d",&x);
62             printf("%d
",find(x));
63         }
64     }
65     return 0;
66 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/6479046.html