hdu4123(树的直径+ST算法)

来源:互联网 发布:算命软件破解版 编辑:程序博客网 时间:2024/06/05 16:47

链接:点击打开链接

题意:给出一棵树,标号1~n,每条边都有边权,数组num[i]为树上标号为i的点到其他点的最大距离,然后有一些询问,每个询问输入一个整数m,求num数组中最大值与最小值绝对值之差不超过m的最长的连续区间的大小是多少

代码:

#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;struct node{    int to,cost;};vector<node> G[50005];int n,a[50005],dp[50005],vis[50005],dis[50005][5];void dfs1(int s){    int i,tmp;    for(i=0;i<G[s].size();i++){        tmp=G[s][i].to;        if(G[tmp].size())        dfs1(tmp);        if(dis[tmp][0]+G[s][i].cost>dis[s][0]){            dis[s][0]=dis[tmp][0]+G[s][i].cost;            vis[s]=tmp;        }    }    for(i=0;i<G[s].size();i++){        tmp=G[s][i].to;        if(tmp!=vis[s])        dis[s][1]=max(dis[s][1],dis[tmp][0]+G[s][i].cost);    }}void dfs2(int s){    int i,tmp;    for(i=0;i<G[s].size();i++){        tmp=G[s][i].to;        if(tmp==vis[s])        dp[tmp]=max(dp[s],dis[s][1])+G[s][i].cost;        else        dp[tmp]=max(dp[s],dis[s][0])+G[s][i].cost;        dfs2(tmp);    }}int dp1[50005][30],dp2[50005][30];void rmq_init(){    int i,j;    for(i=1;i<=n;i++){        dp1[i][0]=a[i];        dp2[i][0]=a[i];    }    for(j=1;(1<<j)<=n;j++)  {        for(i=1;i+(1<<j)-1<=n;i++){            dp1[i][j]=max(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]);            dp2[i][j]=min(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]);        }    }}                                               //ST算法求rmqint rmq(int x,int y){    int k=0;    while((1<<(k+1))<=y-x+1)    k++;    return max(dp1[x][k],dp1[y-(1<<k)+1][k])-min(dp2[x][k],dp2[y-(1<<k)+1][k]);}int main(){    int i,j,d,q,x,y,z,id,ans;    while(scanf("%d%d",&n,&q)!=EOF&&(n||q)){        memset(dp,0,sizeof(dp));        memset(dis,0,sizeof(dis));        memset(vis,0,sizeof(vis));        for(i=1;i<=n;i++)        G[i].clear();        for(i=2;i<=n;i++){            scanf("%d%d%d",&x,&y,&z);            if(y<x)            swap(x,y);            G[x].push_back((node){y,z});        }        dfs1(1);        dfs2(1);        for(i=1;i<=n;i++)        a[i]=max(dis[i][0],dp[i]);              //求树上两点间最大距离可以先做hdu2196        rmq_init();                             //阶梯报告:http://blog.csdn.net/stay_accept/article/details/50813783            while(q--){            id=1,ans=0;            scanf("%d",&d);            for(i=1;i<=n;i++){                  //用尺取法求最大长度                while(id<=i&&rmq(id,i)>d)                id++;                ans=max(ans,i-id+1);            }            printf("%d\n",ans);        }    }    return 0;}


 

0 0
原创粉丝点击