题意:
给定n个点的带边权树Q个询问。
下面n-1行给出树
设dp[i]表示树上离 i 点最远点的距离
下面Q行每行一个数字表示询问。
询问L, 表示求出 dp 数组中最长的连续子序列使得序列中最大值-最小值 <= L,输出这个序列的长度。
思路:
求dp数组就是求个树的直径然后dfs一下。
接着就和这题一样了。
对于每个询问,可以用一个单调队列维护一下。O(n)的回答。
Bob’s Race
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2639 Accepted Submission(s): 840
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 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
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include <cmath>
using namespace std;
#define ll long long
#define prt(k) ;//cerr<<#k" = "<<k<<endl
const int N = 50050;
const int M = 2 * N;
int n, m;
const ll inf = 0x3f3f3f3f;
int head[M], to[M], next[M], cost[M];
int tot;
void initEdge()
{
tot = 0;
memset(head, -1, sizeof head);
}
void addEdge(int u, int v, int w)
{
to[++tot] = v, cost[tot] = w;
next[tot] = head[u];
head[u] = tot;
}
ll dis[N];
int pre[N];
int BFS(int x) ///return farest point from x
{
memset(dis, -1, sizeof dis);
dis[x] = 0;
pre[x] = -1;
int far = x;
queue<int> q;
q.push(x);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];~i;i=next[i])
{
int v = to[i];
if(dis[v]==-1)
{
dis[v] = dis[u] + cost[i];
pre[v] = u;
if(dis[far] < dis[v])
far = v;
q.push(v);
}
}
}
return far;
}
ll dp[N];
bool vis[N];
void dfs(int u)
{
vis[u] = true;
for(int i=head[u];~i;i=next[i])
{
int v = to[i];
if(vis[v]) continue;
dp[v] = dp[u] + cost[i];
dfs(v);
}
}
int stk[N];
int len;
void build() ///预处理树的直径
{
int E = BFS(1);
int S = BFS(E);
int top = 0;
int u = S;
len = dis[S];
memset(vis, 0, sizeof vis);
while(u != -1)
{
stk[top++] = u;
dp[u] = max(dis[u], len - dis[u]);
vis[u] = true;
u = pre[u];
}
for(int i=0;i<top;i++) dfs(stk[i]);
}
int qMax[M], qMin[M];
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m)==2, n+m)
{
initEdge();
for(int i=0;i<n-1;i++)
{
int u,v,w;
scanf("%d%d%d", &u,&v,&w);
addEdge(u,v,w);
addEdge(v,u,w);
}
build();
// for(int i=1;i<=n;i++) printf("dp[%d] = %d\n",i,dp[i]);
while(m--)
{
int v; scanf("%d",&v);
int ans, hmax, tmax, hmin, tmin;
ans=hmax=tmax=hmin=tmin=0;
int st = 0;
tmax=tmin=-1;
for(int i=1;i<=n;i++)
{
while(hmax<=tmax&&dp[qMax[tmax]]<dp[i]) --tmax;
qMax[++tmax] = i;
while(hmin<=tmin&&dp[qMin[tmin]]>dp[i]) --tmin;
qMin[++tmin] = i;
while(dp[qMax[hmax]]-dp[qMin[hmin]] > v)
{
if(qMax[hmax]<=qMin[hmin])
st = qMax[hmax++];
else
st = qMin[hmin++];
}
ans=max(ans, i-st);
}
printf("%d\n", ans);
}
}
}