[HDU4123]Bob’s Race

题目大意:
给定一棵$n$个点并且有边权的树,每个点的权值为该点能走的最远长度,并输入$m$个询问,每次询问最多有多少个编号连续的点,他们的最大最小点权差小于等于$Q$。

思路:
两趟DP(DFS)求出每个点能走的最远长度,然后用ST算法预处理出每一段最大最小值。
对于每组询问,用尺取法求出最大值。
注意log2不能用cmath里面的函数(尤其是不能在for语句上),不然会TLE,最好是自己实现。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<vector>
 4 inline int getint() {
 5     char ch;
 6     while(!isdigit(ch=getchar()));
 7     int x=ch^‘0‘;
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^‘0‘);
 9     return x;
10 }
11 inline int log2(const float x){
12     return ((unsigned&)x>>23&255)-127;
13 }
14 const int N=50001,logN=16;
15 struct Edge {
16     int to,w;
17 };
18 std::vector<Edge> e[N];
19 inline void add_edge(const int u,const int v,const int w) {
20     e[u].push_back((Edge){v,w});
21 }
22 int w[N][3],son[N];
23 void dfs1(const int x,const int par) {
24     w[x][0]=w[x][1]=0;
25     for(unsigned i=0;i<e[x].size();i++) {
26         int &y=e[x][i].to;
27         if(y==par) continue;
28         dfs1(y,x);
29         if(w[y][0]+e[x][i].w>w[x][0]) {
30             w[x][1]=w[x][0];
31             w[x][0]=w[y][0]+e[x][i].w;
32             son[x]=y;
33         }
34         else if(w[y][0]+e[x][i].w>w[x][1]) {
35             w[x][1]=w[y][0]+e[x][i].w;
36         }
37     }
38 }
39 void dfs2(const int x,const int par) {
40     for(unsigned i=0;i<e[x].size();i++) {
41         int &y=e[x][i].to;
42         if(y==par) continue;
43         w[y][2]=std::max(w[x][2],son[x]!=y?w[x][0]:w[x][1])+e[x][i].w;
44         dfs2(y,x);
45     }
46 }
47 int max[N][logN],min[N][logN];
48 inline int getsum(const int l,const int r) {
49     int k=log2(r-l+1);
50     return std::max(max[l][k],max[r-(1<<k)+1][k])-std::min(min[l][k],min[r-(1<<k)+1][k]);
51 }
52 int main() {
53     for(;;) {
54         int n=getint(),m=getint();
55         if(!n&&!m) return 0;
56         for(int i=1;i<n;i++) {
57             int u=getint(),v=getint(),w=getint();
58             add_edge(u,v,w);
59             add_edge(v,u,w);
60         }
61         dfs1(1,0);
62         dfs2(1,0);
63         for(int i=1;i<=n;i++) {
64             max[i][0]=min[i][0]=std::max(w[i][0],w[i][2]);
65         }
66         for(int j=1;1<<j<=n;j++) {
67             for(int i=1;i<=n-(1<<j)+1;i++) {
68                 max[i][j]=std::max(max[i][j-1],max[i+(1<<(j-1))][j-1]);
69                 min[i][j]=std::min(min[i][j-1],min[i+(1<<(j-1))][j-1]);
70             }
71         }
72         while(m--) {
73             int q=getint(),ans=0;
74             for(int l=1,r=1;l<=r;l++) {
75                 for(;r<=n&&getsum(l,r)<=q;r++);
76                 ans=std::max(ans,r-l);
77             }
78             printf("%d\n",ans);
79         }
80         for(int i=1;i<=n;i++) e[i].clear();
81     }
82 }
时间: 2024-12-16 22:04:16

[HDU4123]Bob’s Race的相关文章

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

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 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’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&#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

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的最大值 思路是首先预处理出每个点到其他点的最大距离, 这可以通过

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 树形DP+RMQ

http://acm.hdu.edu.cn/showproblem.php?pid=4123 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,