hdu 4123 rmq与树的直径

26 篇文章 0 订阅
3 篇文章 0 订阅
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int inf = 0x7f7f7f7f;
const int maxn = 5e4 + 10;
deque<int> Max, Min;
struct node{
    int v, w;
    node(){}
    node(int _v, int _w){
        v = _v; w = _w;
    }
};
int LOG[2*maxn]; 
int dp1[20][2*maxn]; 
int dp2[20][2*maxn];
int num[maxn];
void rmq_init(int n) 
{ 
    int i,j; 
    for(j=1;j<=n;j++)   { 
        dp1[0][j]=num[j]; 
        dp2[0][j]=num[j]; 
    } 
    for(j=1;j<=LOG[n];j++)   { 
        int limit=n+1-(1<<j); 
        for(i=1;i<=limit;i++)    { 
            int x=i+(1<<(j - 1)); //省赛时就被这里坑了
            dp1[j][i]=min(dp1[j-1][x],dp1[j-1][i]); 
            dp2[j][i]=max(dp2[j-1][x],dp2[j-1][i]); 
        } 
    } 
} 
int rmq_min(int l,int r) 
{ 
    int m=LOG[r-l+1]; 
    return min(dp1[m][l],dp1[m][r-(1<<m)+1]); 
} 
int rmq_max(int l,int r) 
{ 
    int m=LOG[r-l+1]; 
    return max(dp2[m][l],dp2[m][r-(1<<m)+1]); 
} 
int n, m, x, y, z, q;
int vis[maxn];
vector<node>aa[maxn];
int disf[maxn], diss[maxn], a[maxn];
void bfs(int s, int &ss, int dist[]){
    memset(dist, inf, sizeof( dist ));
    memset(vis, 0 ,sizeof( vis ));
    queue<int> q;
    int maxx = 0;
    q.push(s); vis[s] = 1; dist[s] = 0;
    while(!q.empty() ){
        int now = q.front(); q.pop();
        for(int i = 0 ; i < aa[now].size(); i++){
            int v = aa[now][i].v; int w = aa[now][i].w;
            if(vis[v]) continue;
            vis[v] = 1;
            dist[v] = dist[now] + w;
            if(dist[v] > maxx){
                maxx = dist[v]; ss = v;
            }
            q.push(v);
        }
    }
}
int main(){
    LOG[0] = -1; 
    for(int i = 1;i < 2 * maxn; i++) LOG[i] = LOG[i>>1] + 1;
    while(scanf("%d%d", &n, &q) , n || q){
        for(int i = 1 ; i <= n ; i ++) aa[i].clear();
        for(int i = 1 ;i < n ; i ++){
            scanf("%d%d%d", &x, &y, &z);
            aa[x].push_back(node(y, z));
            aa[y].push_back(node(x, z));
        }
        int ss, tt;
    //  puts("nima");
        bfs(1, ss, disf);//cout<<" ss = "<<ss<<endl;
        bfs(ss, tt, disf);//cout<<" ff = "<<tt<<endl;
        bfs(tt, ss, diss);
    //  puts("nimab");
        for(int i = 1; i <= n; i++)     num[i] = max(disf[i], diss[i]);
    //  for(int i = 1; i <= n; i++)     cout << " i = " <<i<<" "<< disf[i] <<endl;
    //  while( !Max.empty() ) Max.pop_back() ;
      //  while( !Min.empty() ) Min.pop_back() ;
        int i, j; int ans;
        //puts("nimabi ");
        rmq_init(n); 
        while(q--)    { 
            scanf("%d",&m); 
            int ans = 0; 
            int l = 1,r = 1, mx, mi; 
            while(r <= n)    { 
                mx = rmq_max(l, r); 
                mi = rmq_min(l, r); 
                if(mx - mi <= m )    { 
                    ans = max(ans, r - l + 1); 
                    r++; 
                } 
                else l++; 
            } 
            printf("%d\n",ans);
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值