题意:
给出一棵树,每个点有一个到其它点的最远距离,求最长编号连续的点集的大小,需要满足最大的最远距离减去最小的最远距离小于等于q
思路:
求一个点到其它点的最远距离简单的树形dp就可以处理,需要求出每个点的最远距离,可以是采用换根dp,就需要对每个点维护一个最大和次大值。
得到每个点得最远距离后,可以使用st表处理区间最大最小值,再利用尺取可以把复杂度维持在Om*n。太多的log运算可能会导致T,预处理解决。
参考代码:
#include<iostream>
#include<algorithm>
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;
const int N=5e4+5;
int log_2[N];
int head[N],cnt;
struct _edge{
int v,w,nxt;
}edge[N<<1];
void add_edge(int u,int v,int w){
edge[++cnt].v=v;
edge[cnt].w=w;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
int dp[N][2],from[N];
void dfs1(int u,int fa){
dp[u][0]=dp[u][1]=0;
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].v;
int w=edge[i].w;
if(v==fa)continue;
dfs1(v,u);
if(dp[v][1]+w>dp[u][0]){
dp[u][0]=dp[v][1]+w;
}
if(dp[u][0]>dp[u][1]){
swap(dp[u][0],dp[u][1]);
from[u]=v;
}
}
// printf("u:%d max1:%d max2:%d from:%d\n",u,dp[u][1],dp[u][2],from[u]);
}
int mp[N];
int stmaxs[N][20],stmins[N][20];
void dfs2(int u,int fa){
mp[u]=dp[u][1];
int tmp[2];
tmp[0]=dp[u][0];
tmp[1]=dp[u][1];
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].v;
int w=edge[i].w;
if(v==fa)continue;
int vfrom=from[v];
if(from[u]==v){
if(dp[u][0]+w>dp[v][0]){
dp[v][0]=dp[u][0]+w;
}
if(dp[v][0]>dp[v][1]){
swap(dp[v][0],dp[v][1]);
from[v]=u;
}
}
else{
if(dp[u][1]+w>dp[v][0]){
dp[v][0]=dp[u][1]+w;
}
if(dp[v][0]>dp[v][1]){
swap(dp[v][0],dp[v][1]);
from[v]=u;
}
}
dfs2(v,u);
from[v]=vfrom;
}
dp[u][0]=tmp[0];
dp[u][1]=tmp[1];
}
void build(int n)
{
for (int i=1;i<=n;i++){
stmaxs[i][0]=mp[i];
stmins[i][0]=mp[i];
}
for (int j=1;(1<<j)<=n;j++)
for (int i=1;i+(1<<j)-1<=n;i++){
stmaxs[i][j]=max(stmaxs[i][j-1],stmaxs[i+(1<<(j-1))][j-1]);
stmins[i][j]=min(stmins[i][j-1],stmins[i+(1<<(j-1))][j-1]);
}
}
int query_max(int l,int r)
{
if(r<l)
return -1;
int len=log_2[r-l+1];
return max(stmaxs[l][len],stmaxs[r-(1<<len)+1][len]);
}
int query_min(int l,int r)
{
if(r<l)
return -1;
int len=log_2[r-l+1];
return min(stmins[l][len],stmins[r-(1<<len)+1][len]);
}
int main(){
log_2[1]=0;
int xx=2,ct=1;
while (xx<N){
log_2[xx]=ct;
xx<<=1;
ct++;
}
for(int i=3;i<N;i++){
if(!log_2[i]){
log_2[i]=log_2[i-1];
}
}
int n,m;
while (~scanf("%d%d",&n,&m)&&n+m){
cnt=0;
memset(head,-1, sizeof(head));
for(int i=1,u,v,w;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
dfs1(1,-1);
dfs2(1,-1);
// for(int i=1;i<=n;i++){
// printf("%d%c",mp[i],i==n?'\n':' ');
// }
build(n);
for(int i=1,q;i<=m;i++){
scanf("%d",&q);
int l=1,r=0;
int ans=0;
while (r<n){
while (query_max(l,r)-query_min(l,r)<=q&&r<=n){
r++;
}
ans=max(ans,r-l);
l++;
}
printf("%d\n",ans);
}
}
return 0;
}
版权声明:本文为qq_40942372原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。