hdu 4123 树的最长路+RMQ

Bob’s Race

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3034    Accepted Submission(s): 991

Problem Description
Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses, and all houses are connected together. To make the race more interesting, he requires that every participant must start from a different house and run AS FAR AS POSSIBLE without passing a road more than once. The distance difference between the one who runs the longest distance and the one who runs the shortest distance is called “race difference” by Bob. Bob does not want the “race difference”to be more than Q. The houses are numbered from 1 to N. Bob wants that the No. of all starting house must be consecutive. He is now asking you for help. He wants to know the maximum number of starting houses he can choose, by other words, the maximum number of people who can take part in his race.
 
Input
There are several test cases.
The first line of each test case contains two integers N and M. N is the number of houses, M is the number of queries.
The following N-1 lines, each contains three integers, x, y and z, indicating that there is a road of length z connecting house x and house y.
The following M lines are the queries. Each line contains an integer Q, asking that at most how many people can take part in Bob’s race according to the above mentioned rules and under the condition that the“race difference”is no more than Q. 

The input ends with N = 0 and M = 0.

(N<=50000 M<=500 1<=x,y<=N 0<=z<=5000 Q<=10000000)
 
Output
For each test case, you should output the answer in a line for each query.
 
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

树的最长路:

用搜索的方法求某个点的最远的点的距离了,就是先对任意一个点求距离其最远的顶点,最后可以得到一条树的直径的两个端点,以这两个端点开始去遍历整棵树,两个端点到每个点的距离较大值就会是这个点在树上能够走的最远距离


/*
hdu4123
给你n个点,被n-1条边连着,求出以他们每个点为起点的最长路(不可重复走),
然后是m个查询,找出它们的最长连续串max-min<q
树的最长路 + RMQ
hhh-2016-01-31 03:04:55
*/

#include <functional>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <Map>
using namespace std;
typedef long long ll;
typedef long double ld;

using namespace std;

const int maxn = 50005;

ll dp1[maxn][20];
ll dp2[maxn][20];
int mm[maxn+5];
ll sum[maxn];
int tot;
int head[maxn];

ll min(ll a,ll b)
{
    return a < b ? a:b;
}

ll max(ll a,ll b)
{
    return a > b ? a:b;
}

struct node
{
    int to,next;
    ll w;
} edge[maxn*2];

void addedge(int u,int v,int w)
{
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void iniRMQ(int n,ll c[])
{
    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]=dp2[i][0]= c[i];
    }
    for(int j = 1; j <= mm[n]; j++)
    {
        for(int i = 1; i+(1<<j)-1 <= n; i++)
        {
            dp1[i][j] = min(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]);
            dp2[i][j] = max(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]);
        }
    }
}

ll RMQ(int x,int y)
{
    int k = mm[y-x+1];
    return (ll)max(dp2[x][k],dp2[y-(1<<k)+1][k])-(ll)min(dp1[x][k],dp1[y-(1<<k)+1][k]);
}
int id;
ll tall;

void dfs(int u,int pre,ll cnt)    //先找出最远点
{
    if(cnt >= tall)
    {
        id = u;
        tall = cnt;
    }
    for(int i = head[u]; ~i; i = edge[i].next)
    {
        if(edge[i].to == pre) continue;
        dfs(edge[i].to,u,edge[i].w+cnt);
    }
}

void cal(int u,int pre,ll cnt)
{
    for(int i = head[u]; ~i; i = edge[i].next)
    {
        int v = edge[i].to;
        if(v == pre)
            continue;
        sum[v] = max(sum[v],cnt+edge[i].w);
        cal(v,u,cnt+edge[i].w);
    }
}

int main()
{
    int m,n,k;
    while(scanf("%d%d",&n,&m) && n && m)
    {
        int u,v,val;
        tot = 0;
        memset(head,-1,sizeof(head));
        memset(sum,0,sizeof(sum));
        for(int i = 1; i < n; i++)
        {
            scanf("%d%d%d",&u,&v,&val);
            addedge(u,v,val);
            addedge(v,u,val);
        }
        tall = 0;
        dfs(1,0,0);
        cal(id,0,0);
        int t = 1;
        for(int i = 1;i <= n;i++)
            if(sum[i] > sum[t]) t = i;
//        printf("%d %d
",id,t);
        cal(t,0,0);
//        for(int i = 1;i <= n;i++)
//            printf("%d ",sum[i]);
//        cout << endl;
        iniRMQ(n,sum);
        while(m--)
        {
            scanf("%d",&k);
            int ans = 0;
            int td = 1;
            for(int i = 1;i <= n;i++)
            {
                while(td <= i && RMQ(td,i) > k) td++;
                ans = max(ans,i-td+1);
            }
            printf("%d
",ans);
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/Przz/p/5409632.html