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 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

HINT

题意

一个城镇有N个住户,N-1条路连接两个住户,保证N个住户联通,M次询问,给定N条边的信息,包括连
接的住户序号以及路的长度。然后是M次询问,每次询问Q,要求找到最长的连续序号(我一开始看成了树上连续一段),使得Max(dis[i]) - Min(dis[i]) ≤
Q(l≤i≤r),输出最大的r-l+1。dis[i]为从第i个住户出发,不重复走过路能移动的最远距离。

题解:

1.首先需要知道一个 结论:树上每个节点理他最远的点肯定是数的直径的两个端点的其中一个。

2.如果你不会求树的直径以及两个端点,没关系,其实不难,任意找一个点dfs找到离它最远的点root1,root1一定是其中一个端点,然后再以root1为根dfs一遍求出理root1最远的点root2。这样就找到了两个端点。

3.求出每个点到最远点的距离,我这里是分别以root1,root2 dfs,求出每个点到root1和root2的距离,取个max即可。

4.题目转化成了,求最长的区间(l,r),满足max{l,r}-min{l,r}<=q。

5.其实可以用尺取法来做,因为假如(l,r)区间合法,那么(l+1,r)一定合法,那么枚举左端点,右端点只能单增,时间复杂度是O(n)的。

6.最后要搞个ST表求区间最大最小值。

我一开始用优先队列做的,然后T了,真是花样作死,非要加个log。

衷心提示:k=(int)(log(y-x+1)/2)会超时,这个需要预处理,亲测一个1.5s,另一个5.2秒。

优先队列tle代码

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 50050
int n,m,val[N],dp1[N],dp2[N],flag[N];
int tot,last[N];
struct Edge{int from,to,val,s;}edges[N<<];
struct Node
{
int id,val;
bool operator <(const Node&b)const
{return val<b.val;}
};
template<typename T>void read(T&x)
{
ll k=; char c=getchar();
x=;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit();
while(isdigit(c))x=x*+c-'',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void AddEdge (int x,int y,int z)
{
edges[++tot]=Edge{x,y,z,last[x]};
last[x]=tot;
}
void dfs1(int x,int pre,int &mx,int &root)
{
mx=; root=x;
int tpmx,tproot;
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
dfs1(e.to,x,tpmx,tproot);
if (tpmx+e.val>mx)
{
mx=tpmx+e.val;
root=tproot;
}
}
}
void dfs2(int x,int pre,int *dp)
{
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
dp[e.to]=dp[x]+e.val;
dfs2(e.to,x,dp);
}
} void init()
{
read(n); read(m);
if (n==&&m==)exit();
for(int i=;i<=n-;i++)
{
int x,y,z;
read(x); read(y); read(z);
AddEdge(x,y,z);
AddEdge(y,x,z);
}
int maxn=,root1,root2;
dfs1(,,maxn,root1);
dfs1(root1,,maxn,root2);
dfs2(root1,,dp1);
dfs2(root2,,dp2);
for(int i=;i<=n;i++) val[i]=max(dp1[i],dp2[i]);
}
void solve()
{
int r=,ans=,q;
read(q);
priority_queue<Node>Qmx,Qmi;
memset(flag,,sizeof(flag));
for(int i=;i<=n;i++)
{
while(r+<=n&&(Qmx.empty()||
(fabs(val[r+]-Qmx.top().val)
<=q&&fabs(val[r+]+Qmi.top().val)<=q)))
{
Qmx.push(Node{r+,val[r+]});
Qmi.push(Node{r+,-val[r+]});
r++;
}
ans=max(ans,r-i+);
flag[i]=;
while(!Qmx.empty()&&flag[Qmx.top().id])Qmx.pop();
while(!Qmi.empty()&&flag[Qmi.top().id])Qmi.pop();
}
printf("%d\n",ans);
}
void clear()
{
tot=;
memset(last,,sizeof(last));
memset(dp1,,sizeof(dp1));
memset(dp2,,sizeof(dp2));
memset(flag,,sizeof(flag));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
while()
{
clear();
init();
for(int i=;i<=m;i++) solve();
}
}

ST表AC代码

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 50050
int n,m,dp1[N],dp2[N],mx[N][],mi[N][],mm[N];
int tot,last[N];
struct Edge{int from,to,val,s;}edges[N<<];
template<typename T>void read(T&x)
{
ll k=; char c=getchar();
x=;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit();
while(isdigit(c))x=x*+c-'',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void AddEdge (int x,int y,int z)
{
edges[++tot]=Edge{x,y,z,last[x]};
last[x]=tot;
}
void dfs1(int x,int pre,int &mx,int &root)
{
mx=; root=x;
int tpmx,tproot;
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
dfs1(e.to,x,tpmx,tproot);
if (tpmx+e.val>mx)
{
mx=tpmx+e.val;
root=tproot;
}
}
}
void dfs2(int x,int pre,int *dp)
{
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
dp[e.to]=dp[x]+e.val;
dfs2(e.to,x,dp);
}
} void init()
{
read(n); read(m);
if (n==&&m==)exit();
for(int i=;i<=n-;i++)
{
int x,y,z;
read(x); read(y); read(z);
AddEdge(x,y,z);
AddEdge(y,x,z);
}
int maxn=,root1,root2;
dfs1(,,maxn,root1);
dfs1(root1,,maxn,root2);
dfs2(root1,,dp1);
dfs2(root2,,dp2);
for(int i=;i<=n;i++) mx[i][]=mi[i][]=max(dp1[i],dp2[i]);
}
void init_ST()
{
mm[]=-;
for(int i=;i<=n;i++)mm[i]=(i&(i-))==?mm[i-]+:mm[i-];
for(int i=;i<=;i++)
for(int j=;j+(<<i)-<=n;j++)
{
mx[j][i]=max(mx[j][i-],mx[j+(<<(i-))][i-]);
mi[j][i]=min(mi[j][i-],mi[j+(<<(i-))][i-]);
}
}
int rmq(int x,int y)
{
int k=mm[y-x+];
int ans=max(mx[x][k],mx[y-(<<k)+][k]);
ans-=min(mi[x][k],mi[y-(<<k)+][k]);
return ans;
}
void solve()
{
int r=,ans=,q;
read(q);
for(int i=;i<=n;i++)
{
while(r+<=n&&rmq(i,r+)<=q)r++;
ans=max(ans,r-i+);
}
printf("%d\n",ans);
}
void clear()
{
tot=;
memset(last,,sizeof(last));
memset(dp1,,sizeof(dp1));
memset(dp2,,sizeof(dp2));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
clock_t now=clock();
while()
{
clear();
init();
init_ST();
for(int i=;i<=m;i++) solve();
} }

HDU 4123 Bob’s Race 树的直径+ST表的更多相关文章

  1. HDU 4123 Bob’s Race 树的直径 RMQ

    Bob’s Race Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=41 ...

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

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Probl ...

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

    题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...

  4. [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树)

    [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树) 题面 给出一棵N个点的树,Q次询问一点编号在区间[l1,r1]内,另一点编号在区间[l2,r2]内的所有点对距离最大值.\ ...

  5. HDU 4123 Bob's Race:树的直径 + 单调队列 + st表

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123 题意: 给你一棵树,n个节点,每条边有长度. 然后有m个询问,每个询问给定一个q值. 设dis[ ...

  6. HDU 4123 Bob’s Race 树形dp+单调队列

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 Time Limit: 5000/2000 MS (Java/Others) Memory L ...

  7. hdu 4123 Bob’s Race (dfs树上最远距离+RMQ)

    C - Bob’s Race Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Subm ...

  8. HDU 4123 Bob’s Race(树形DP,rmq)

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. 刷题总结——Bob's Race(hdu4123 树形dp+st表)

    题目: Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the ro ...

随机推荐

  1. [JSOI 2016] 最佳团体(树形背包+01分数规划)

    4753: [Jsoi2016]最佳团体 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2003  Solved: 790[Submit][Statu ...

  2. MySQL Innodb引擎和MyIASM引擎的区别

    Innodb引擎 Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别.该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL ...

  3. 单调队列优化DP——习题收集

    前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...

  4. UVA 247 Calling Circles —— (强连通分量模板题)

    第一个强连通分量的题. 题意:有一堆人,a给b打电话表示a有一条向b的边,一个强连通分量代表一个电话圈,把每个电话圈里的人在一行内输出出来. 直接上模板即可,但是要注意把string用map映射一下的 ...

  5. 【零基础】搞懂GPU为什么比CPU“快”

    一.前言 近几年深度学习在各领域大显神威,而”GPU加速"也得到了越来越多的篇幅,似乎任何程序只要放到GPU上运行那速度就是杠杠的.GPU代替CPU计算已成了大势所趋?我先告诉你结论”那是不 ...

  6. ubuntu 安装eclipse for c++

    linux的GUI和windos比起来实在逊色,虽然它的终端模式(命令行模式)非常强大.linux发行版ubuntu的GUI相对其他版本要华丽一些,所以最近由redhat转向ubuntu进行linux ...

  7. 20175329&20175313&20175318 2019-2020 《信息安全系统设计基础》实验二

    我们一个小组都在实验前40mins提前做完但是因为队员截图发的迟没能及时提交上蓝墨云班课的任务超时 希望老师能看见将我的经验改正,谢谢老师 https://www.cnblogs.com/xiannv ...

  8. Android input输入框 移动页面input手机键盘中的“搜索”按键

    动页面input手机键盘中的“搜索”按键 满足以下几点机即可: input type="search"    放到form标签中    使用action属性 <form ac ...

  9. git基本操作命令和安装

    git客户端下载及安装 git.png git官方下载链接 1. 添加到桌面 添加到桌面.png (1)图标组件(Addition icons) : 选择是否创建桌面快捷方式. (2)桌面浏览(Win ...

  10. leetcode16 最接近的三数之和

    做了几周的hard之后,这道题居然轻易就解出来了,稍微debug了一下就ac了,算是有了一丢丢提高把: 思路 这道题因为和三数之和很像,所以充分利用双指针的思想:先排序,然后再固定一个数i,i取值从[ ...