hdoj 4123 Bob’s Race 【树的直径 + RMQ】 【二分查询会超时】
来源:互联网 发布:守望者 知乎 编辑:程序博客网 时间:2024/05/25 19:57
Bob’s Race
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2776 Accepted Submission(s): 896
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)
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 51 2 32 3 44 5 33 4 2123450 0
Sample Output
13335
大致题意:给出N个点和N-1条边(它们构成一棵树)。每个节点在树中都有最长路,对于 i 节点的最长路我们用A[ i ]来表示,那么我们就得到一个A[ i ] (1 <= i <= N)序列。现在给一个Q,让你在序列A[] 中 找到一个最长的连续区间 使得该区间里面的最大值和最小值之差不超过Q。
设树的直径为 S - T 路径
思路:先利用树的直径求出每个节点的最长路(节点的最长路 要么是它到S的距离 要么是它到T的距离),然后用RMQ预处理区间最大值和最小值,枚举起点更新最值。
这个方法有点慢,看来要学单调队列了。。。
超时代码:二分查找最优区间 醉了。。。
#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define MAXN 50000+10#define MAXM 100000+10using namespace std;struct Edge{ int from, to, val, next;};Edge edge[MAXM];int head[MAXN], edgenum;int dist[MAXN];bool vis[MAXN];int N, M;//N个点 M次查询int S, T;//最长路两个端点int d1[MAXN], d2[MAXN];//分别存储最长路两个端点到该点的距离void init(){ edgenum = 0; memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w){ Edge E = {u, v, w, head[u]}; edge[edgenum] = E; head[u] = edgenum++;}void getMap(){ int a, b, c; for(int i = 2; i <= N; i++) { scanf("%d%d%d", &a, &b, &c); addEdge(a, b, c); addEdge(b, a, c); }}int BFS(int sx){ queue<int> Q; memset(dist, 0, sizeof(dist)); memset(vis, false, sizeof(vis)); vis[sx] = true; int ans = 0; int node = sx; Q.push(sx); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(!vis[E.to] && dist[E.to] < dist[u] + E.val) { vis[E.to] = true; dist[E.to] = dist[u] + E.val; if(dist[E.to] > ans) { ans = dist[E.to]; node = E.to; } Q.push(E.to); } } } return node;}//RMQ求满足 最大值最小值之差不大于Q的 最大区间int A[MAXN];//存储每个点的最长路int Amax[MAXN][30];int Amin[MAXN][30];void RMQ_init()//预处理区间 最大值 最小值{ for(int i = 1; i <= N; i++) Amax[i][0] = Amin[i][0] = A[i]; for(int j = 1; (1<<j) <= N; j++) { for(int i = 1; i + (1<<j) - 1 <= N; i++) { Amax[i][j] = max(Amax[i][j-1], Amax[i + (1<<(j-1))][j-1]); Amin[i][j] = min(Amin[i][j-1], Amin[i + (1<<(j-1))][j-1]); } }}int query(int L, int R)//求区间[L, R]最大值最小值 之差{ int k = 0; while(1<<(k+1) <= R-L+1) k++; return max(Amax[L][k], Amax[R-(1<<k) + 1][k]) - min(Amin[L][k], Amin[R-(1<<k) + 1][k]);}void solve(){ S = BFS(1);//找到一个端点 T = BFS(S);//以找到的端点为起点 找另一个端点 //printf("%d\n", T); for(int i = 1; i <= N; i++) d1[i] = dist[i];//S为起点 到各点的最长路 BFS(T);//以另一个端点为起点 for(int i = 1; i <= N; i++) { d2[i] = dist[i];//T为起点 到各点的最长路 A[i] = max(d1[i], d2[i]); } RMQ_init();//RMQ预处理 int Q; while(M--) { scanf("%d", &Q); int ans = 0; for(int i = 1; i <= N; i++) { //二分查找最优区间 //只是终止条件 和 区间更替不太一样 int left = i, right = N, mid; while(right - left > 1) { mid = (left + right) >> 1; if(query(i, mid) > Q) right = mid; else left = mid; } if(query(i, right) <= Q) ans = max(ans, right - i + 1); else ans = max(ans, left - i + 1); } printf("%d\n", ans); }}int main(){ while(scanf("%d%d", &N, &M), N||M) { init(); getMap(); solve(); } return 0;}
AC代码:
#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define MAXN 50000+10#define MAXM 100000+10using namespace std;struct Edge{ int from, to, val, next;};Edge edge[MAXM];int head[MAXN], edgenum;int dist[MAXN];bool vis[MAXN];int N, M;//N个点 M次查询int S, T;//最长路两个端点int d1[MAXN], d2[MAXN];//分别存储最长路两个端点到该点的距离void init(){ edgenum = 0; memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w){ Edge E = {u, v, w, head[u]}; edge[edgenum] = E; head[u] = edgenum++;}void getMap(){ int a, b, c; for(int i = 2; i <= N; i++) { scanf("%d%d%d", &a, &b, &c); addEdge(a, b, c); addEdge(b, a, c); }}int BFS(int sx){ queue<int> Q; memset(dist, 0, sizeof(dist)); memset(vis, false, sizeof(vis)); vis[sx] = true; int ans = 0; int node = sx; Q.push(sx); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(!vis[E.to] && dist[E.to] < dist[u] + E.val) { vis[E.to] = true; dist[E.to] = dist[u] + E.val; if(dist[E.to] > ans) { ans = dist[E.to]; node = E.to; } Q.push(E.to); } } } return node;}//RMQ求满足 最大值最小值之差不大于Q的 最大区间int A[MAXN];//存储每个点的最长路int Amax[MAXN][30];int Amin[MAXN][30];void RMQ_init()//预处理区间 最大值 最小值{ for(int i = 1; i <= N; i++) Amax[i][0] = Amin[i][0] = A[i]; for(int j = 1; (1<<j) <= N; j++) { for(int i = 1; i + (1<<j) - 1 <= N; i++) { Amax[i][j] = max(Amax[i][j-1], Amax[i + (1<<(j-1))][j-1]); Amin[i][j] = min(Amin[i][j-1], Amin[i + (1<<(j-1))][j-1]); } }}int query(int L, int R)//求区间[L, R]最大值最小值 之差{ int k = 0; while(1<<(k+1) <= R-L+1) k++; return max(Amax[L][k], Amax[R-(1<<k) + 1][k]) - min(Amin[L][k], Amin[R-(1<<k) + 1][k]);}void solve(){ S = BFS(1);//找到一个端点 T = BFS(S);//以找到的端点为起点 找另一个端点 //printf("%d\n", T); for(int i = 1; i <= N; i++) d1[i] = dist[i];//S为起点 到各点的最长路 BFS(T);//以另一个端点为起点 for(int i = 1; i <= N; i++) { d2[i] = dist[i];//T为起点 到各点的最长路 A[i] = max(d1[i], d2[i]); } RMQ_init();//RMQ预处理 int Q; while(M--) { scanf("%d", &Q); int ans = 1; int s = 1; for(int i = 1; i <= N; i++) { while(query(s, i) > Q && s < i) s++; ans = max(ans, i - s + 1); } printf("%d\n", ans); }}int main(){ while(scanf("%d%d", &N, &M), N||M) { init(); getMap(); solve(); } return 0;}
0 0
- hdoj 4123 Bob’s Race 【树的直径 + RMQ】 【二分查询会超时】
- HDOJ 题目4123 Bob’s Race(树的直径+RMQ优化)
- hdu 4123 Bob’s Race (树的直径相关+rmq+单调队列思想)
- HDU 4123 Bob’s Race 树的直径+单调队列
- 两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race
- hdu4123-树的直径+ST算法记忆化-Bob’s Race
- HDU 4123 Bob’s Race 树状DP+RMQ预处理
- hdu 4123 Bob’s Race(树形DP&RMQ)
- hdu 4123 Bob’s Race(单调队列或者rmq)
- HDU 4123 Bob’s Race(树形DP+RMQ)
- hdu 4123 Bob’s Race(树形dp+RMQ)
- hdu 4123 Bob’s Race (树上最长路+RMQ)
- HDU 4123 Bob’s Race(树形DP+RMQ)
- HDU 4123 - Bob’s Race(树形DP + RMQ)
- hdu 4123 Bob’s Race 树形DP + RMQ
- HDU 4123 Bob’s Race(树形DP,rmq)
- HDU 4123 Bob’s Race 树形DP + RMQ
- HDU-4123 Bob’s Race(树型dp+RMQ)
- [python]学习笔记4-关于列表去重练习
- NYOJ_119_士兵杀敌(三)(RMQ-ST)
- mysql和oracle的连接
- Java内部类的作用
- Android 与 JDK 下查找包下的类
- hdoj 4123 Bob’s Race 【树的直径 + RMQ】 【二分查询会超时】
- offsetLeft与style.left的区别
- 欢迎使用CSDN-markdown编辑器
- 【前端学习笔记】Javascript中的正则表达式-实例
- 博客第一言
- ZOJ 1671 --Walking Ant【BFS】
- if-mdp使用手册
- 单片机上电延时1s
- NYOJ 811 变态最大值