题意:给出一棵树,结点编号1~n,设每个结点到树上最远距离为Li,m次询问每次询问1~n中连续区间中差值小于等于q的最长子区间长度
题解:首先肯定是要用树的直径处理出每个结点的最远距离,接下来就直接O(n*m)吧,试过不会T,每次询问都扫一遍整个数组得到最长子区间。
最长子区间求法可以单调队列,也可以用RMQ预处理
RMQ取区间差值:
//case2 RMQ取区间差值 nlogn预处理 n查询
int ans = 0;
int id = 1;
for(int i = 1;i <= n;i++)
{
while(id <= i && rmq(id,i) > Q)id++;
ans = max(ans,i-id+1);
}
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 200005
int n,m;
int fir[maxn],nex[maxn],w[maxn],v[maxn];
int e_max;
int L[maxn],R[maxn],Long[maxn],len;
int res[maxn],vis[maxn];
int ansr[1000];
void init()
{
len=0;
memset(ansr,0,sizeof ansr);
memset(res,0,sizeof res);
memset(L,0,sizeof L);
memset(R,0,sizeof R);
memset(fir,-1,sizeof fir);
e_max=0;
}
void add_edge(int s,int t,int c)
{
int e=e_max++;
w[e]=c;
v[e]=t;
nex[e]=fir[s];
fir[s]=e;
}
int ed,cot;
void dfs_long(int k,int fa,int co)
{
if(co>=cot) ed=k,cot=co;
for(int i=fir[k]; ~i; i=nex[i])
{
int e=v[i];
if(e==fa) continue;
dfs_long(e,k,co+w[i]);
}
}
int flag;
void dfs_read(int s,int t,int sum,int fa)
{
if(s==t)
{
flag=1;
Long[++len]=t;
L[len]=sum;
return ;
}
for(int i=fir[s]; ~i; i=nex[i])
{
int e=v[i];
if(e==fa) continue;
dfs_read(e,t,w[i],s);
if(flag)
{
Long[++len]=s;
L[len]=sum;
return ;
}
}
}
void dfs_solve(int k,int sum)
{
vis[k]=1;
res[k]=sum;
for(int i=fir[k]; ~i; i=nex[i])
{
int e=v[i];
if(vis[e]) continue;
dfs_solve(e,sum+w[i]);
}
}
void init_build()
{
memset(vis,0,sizeof vis);
len=0;
ed=cot=0;
int s,t;
dfs_long(1,-1,0);
s=ed;
cot=0;
dfs_long(s,-1,0);
t=ed;
flag=0;
dfs_read(s,t,0,-1);
for(int i=len-1; i>=1; i--)
{
L[i]+=L[i+1];
}
for(int i=1; i<=len; i++)
{
vis[Long[i]]=1;
res[Long[i]]=max(L[i],L[1]-L[i]);
}
for(int i=1; i<=len; i++)
{
dfs_solve(Long[i],max(L[i],L[1]-L[i]));
}
}
int qmin[maxn],qmax[maxn];
int solve(int m,int k)
{
int s=0;
int lm=0,rm=0,lx=0,rx=0,ans=1,l=0;
for(int i=1; i<=n; i++)
{
while(lm<rm && res[qmin[rm-1]]>res[i])rm--;
while(lx<rx && res[qmax[rx-1]]<res[i])rx--;
qmin[rm++]=i;
qmax[rx++]=i;
while(res[qmax[lx]]-res[qmin[lm]]>k)
{
l=(qmin[lm]<qmax[lx])?qmin[lm++]:qmax[lx++];
}
if(res[qmax[lx]]-res[qmin[lm]]>=m)
{
ans=max(ans, i-l);
}
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF&&n+m)
{
init();
for(int i=0; i<n-1; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
add_edge(b,a,c);
}
init_build();
map<int,int>mp;
while(m--)
{
int q,ans=1;
scanf("%d",&q);
if(mp[q])
{
printf("%d\n",mp[q]);
continue;
}
ans=solve(0,q);
printf("%d\n",mp[q]=ans);
}
}
return 0;
}