zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    121. Best Time to Buy and Sell Stock
    分页查询
    ViewPager
    SharedPreferences
    android 动画
    display~
    stringBuffer拼接有规律字符串
    修改placehosder
    this Activity.this Activity.class
    Windows基础编程SDK复习知识点
  • 原文地址:https://www.cnblogs.com/Przz/p/5409632.html
Copyright © 2011-2022 走看看