hdu4123
题目
就是给你一棵树,首先要求出每个点到其他某个点的价值的最大值,然后选取连续的点,使他们之间最大值最小值的差值不能小于询问q,问这样连续的点最多有多少个。
思路
前一个求最大值和hdu2196相同,而后的区间询问可以用rmq来处理,同时利用单调性,如果例如2~4超过了q,那么2~5肯定也超过了q,可以直接从3开始判断了,也就是尺取法,还有就是log很慢,需要预处理一下log结果。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=510000;
int dp[maxn][3];
int mmin[maxn][20];
int mmax[maxn][20];
int n,m;
int flog[maxn];
struct node
{
int next;
int to;
int w;
} edge[maxn];
int head[maxn];
int tot;
void addedge(int from,int to,int w)
{
edge[tot].to=to;
edge[tot].next=head[from];
edge[tot].w=w;
head[from]=tot++;
}
void dfs1(int u,int fa)
{
int bigger=0;
int biggest=0;
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to;
int w=edge[i].w;
if(v==fa) continue;
dfs1(v,u);
if(biggest<dp[v][0]+w)
{
bigger=biggest;
biggest=dp[v][0]+w;
}
else if(bigger<dp[v][0]+w)
{
bigger=dp[v][0]+w;
}
}
dp[u][0]=biggest;
dp[u][1]=bigger;
}
void dfs2(int u,int fa)
{
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to;
int w=edge[i].w;
if(v==fa) continue;
if((dp[u][0]-w)==dp[v][0])
{
dp[v][2]=max(dp[v][2],max(dp[u][2],dp[u][1])+w);
}
else
{
dp[v][2]=max(dp[v][2],max(dp[u][2],dp[u][0])+w);
}
dfs2(v,u);
}
}
void rmq_st(int n)
{
for(int i=0; i<n; i++)
{
mmax[i][0]=mmin[i][0]=max(dp[i+1][0],dp[i+1][2]);
}
//int endj=(int)(log(n+0.0)/log(2.0));
for(int j=1; j<=flog[n]; j++)
{
int endi=n+1-(1<<j);
for(int i=0; i<endi; i++)
{
mmin[i][j]=min(mmin[i][j-1],mmin[i+(1<<(j-1))][j-1]);
mmax[i][j]=max(mmax[i][j-1],mmax[i+(1<<(j-1))][j-1]);
}
}
}
int query_min(int l,int r)
{
//int k=(int)(log(r-l+1.0)/log(2.0));
int k=flog[r-l+1];
return min(mmin[l][k],mmin[r-(1<<k)+1][k]);
}
int query_max(int l,int r)
{
//int k=(int)(log(r-l+1.0)/log(2.0));
int k=flog[r-l+1];
return max(mmax[l][k],mmax[r-(1<<k)+1][k]);
}
int main()
{
for(int i=1; i<=maxn-1; i++)
flog[i]=log2(i);
while(scanf("%d %d",&n,&m)!=EOF)
{
if(m==0&&n==0)
break;
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
tot=0;
for(int i=1; i<n; i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
dfs1(1,-1);
dfs2(1,-1);
rmq_st(n);
while(m--)
{
int d;
int id=1,ans=0;
scanf("%d",&d);
for(int i=1; i<=n; i++)
{
while(id<=i&&(query_max(id-1,i-1)-query_min(id-1,i-1))>d)
id++;
ans=max(ans,i-id+1);
}
printf("%d\n",ans);
}
}
return 0;
}