hdu 4123 Bob’s Race 树的直径+rmq+尺取

Bob’s Race

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

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

Source

2011 Asia Fuzhou Regional Contest

题意:给你一个树,求每个点的最远距离,并且最最大的区间长度小于等于q;

思路:1:树的直径

2:rmq的st表;

   3:尺取;

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pi (4*atan(1.0))
#define eps 1e-14
const int N=1e5+10,M=1e6+10,inf=1e9+10;
const ll INF=1e18+10,mod=2147493647;
struct is
{
    int v,w,nex;
}edge[N];
int head[N],edg;
int node1,node2,deep;
int dis[N],num[N];
int pos[N];
void init()
{
    memset(num,0,sizeof(num));
    memset(head,-1,sizeof(head));
    memset(dis,0,sizeof(dis));
    edg=0;
    deep=0;
}
void add(int u,int v,int w)
{
    edg++;
    edge[edg].v=v;
    edge[edg].w=w;
    edge[edg].nex=head[u];
    head[u]=edg;
}
void dfs(int u,int fa,int val,int &node)
{
    dis[u]=max(dis[u],val);
    if(val>deep)
    {
        deep=val;
        node=u;
    }
    for(int i=head[u];i!=-1;i=edge[i].nex)
    {
        int v=edge[i].v;
        int w=edge[i].w;
        if(v==fa)continue;
        dfs(v,u,val+w,node);
    }
}
int dpi[N][30];
int dpa[N][30];
int minn(int x,int y)
{
    return num[x]<=num[y]?x:y;
}
void rmqi(int len)
{
    for(int i=0; i<len; i++)
    dpi[i][0]=i;
    for(int j=1; (1<<j)<len; j++)
    for(int i=0; i+(1<<j)-1<len; i++)
    dpi[i][j]=minn(dpi[i][j-1],dpi[i+(1<<(j-1))][j-1]);
}
int queryi(int l,int r)
{
    int x=pos[r-l+1];
    return minn(dpi[l][x],dpi[r-(1<<x)+1][x]);
}
int maxx(int x,int y)
{
    return num[x]>=num[y]?x:y;
}
void rmqa(int len)
{
    for(int i=0; i<len; i++)
    dpa[i][0]=i;
    for(int j=1; (1<<j)<len; j++)
    for(int i=0; i+(1<<j)-1<len; i++)
    dpa[i][j]=maxx(dpa[i][j-1],dpa[i+(1<<(j-1))][j-1]);
}
int querya(int l,int r)
{
    int x=pos[r-l+1];
    return maxx(dpa[l][x],dpa[r-(1<<x)+1][x]);
}
int n,m;
int main()
{
    pos[0]=-1;
    for(int i=1;i<100000;i++) pos[i]=pos[i>>1]+1;
    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);
            add(u,v,w);
            add(v,u,w);
        }
        dfs(1,-1,0,node1);
        deep=0;
        dfs(node1,-1,0,node2);
        dfs(node2,-1,0,node1);
        for(int i=1;i<=n;i++)
            num[i]=max(dis[i],num[i]);
        rmqi(n+1);
        rmqa(n+1);
        while(m--)
        {
            int z;
            scanf("%d",&z);
            int l=1,r=1,ans=0;
            while(1)
            {
                while(num[querya(l,r)]-num[queryi(l,r)]<=z&&r<=n)r++;
                ans=max(ans,r-l);
                if(r>n)
                    break;
                l++;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
时间: 2024-10-13 07:09:04

hdu 4123 Bob’s Race 树的直径+rmq+尺取的相关文章

HDU 4123 Bob’s Race 树的直径+单调队列

题意: 给定n个点的带边权树Q个询问. 下面n-1行给出树 下面Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列使得序列中最大值-最小值 <= u,输出这个序列的长度. 思路: 求dp数组就是求个树的直径然后dfs一下. 对于每个询问,可以用一个单调队列维护一下.O(n)的回答. #include <cstdio> #include <cstring> #include <strin

hdu 4123 Bob’s Race (树的直径相关+rmq+单调队列思想)

Bob's Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2115    Accepted Submission(s): 658 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble

HDU 4123 Bob&#39;s Race:单调队列 + st表

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123 题意: 给你一棵树,n个节点,每条边有长度. 然后有m个询问,每个询问给定一个q值. 设dis[i]为:从节点i出发,不重复经过节点,所能够走的最远距离. 每次询问问你:区间[l,r]最长能有多长,同时保证 max{dis[i]} - min{dis[i]} <= q (i∈[l,r]) 题解: 首先有一个结论: 从树上的任意一个节点出发,尽可能往远走,最终一定会到达树的直径的两个端点之一.

hdu 4123 Bob’s Race(树形dp+RMQ)

题目链接:hdu 4123 Bob's Race 题目大意:一个城镇有N个住户,N-1条路连接两个住户,保证N个住户联通,M次询问,给定N条边的信息,包括连 接的住户序号以及路的长度.然后是M次询问,每次询问Q,要求找到最长的连续序号,使得Max(dis[i]) - Min(dis[i]) ≤ Q(l≤i≤r),输出最大的r-l+1.dis[i]为从第i个住户出发,不重复走过路能移动的最远距离. 解题思路:树形dp,通过两次dfs,第1次处理出每个节点中孩子节点移动的最长距离和第二长距离,第2次

HDU 4123 Bob’s Race

Bob’s Race Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4123 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

HDU 4123 Bob’s Race(RMQ)

题意是说给出一棵树,N(10^5)个顶点,以及每条边的权值,现在需要选择连续的K个点(顶点编号连续),可以被选出来的条件是: 若d[i]代表顶点i到树上其他点的距离的最大值,使得区间[a, b]的d值的最大差值不大于Q, 也就是max(d[a], d[a + 1], ..., d[b]) - max(d[a], d[a + 1], ..., d[b]) <= Q Q是给出的一个查询(共有m<=500个查询),求对应每一个查询的K的最大值 思路是首先预处理出每个点到其他点的最大距离, 这可以通过

HDOJ 题目4123 Bob’s Race(树的直径+RMQ优化)

Bob's Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2753    Accepted Submission(s): 888 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble

hdu 4612 缩点 桥 树的直径

// http://acm.hdu.edu.cn/showproblem.php?pid=4612 // 大致题意: 给n个点和m条边,组成一个无向连通图,问  给我加一条边的权力(可连接任意两点)->让图的桥数量最小,输出此时桥的数量.(2<=N<=200000, 1<=M<=1000000) // 无向环里面的边没有桥,缩点,因为是连通图,所以缩完点后构成了一棵树,每条树边都是一个桥.要加一条边使得加完后图的桥数最小,结合上述,所以选择连接树直径的两端点.ans = 原先

F - Warm up - hdu 4612(缩点+求树的直径)

题意:有一个无向连通图,现在问添加一条边后最少还有几个桥 分析:先把图缩点,然后重构图为一棵树,求出来树的直径即可,不过注意会有重边,构树的时候注意一下 *********************************************************************** #pragma comment(linker, "/STACK:102400000,102400000")#include<stdio.h>#include<string.h