zoukankan      html  css  js  c++  java
  • HDU 4123:Bob’s Race RMQ+尺取法

    Bob’s Race

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4123

    题意:

    有一棵树,每条边都有距离,树上每个节点都有一个权值(离这个节点最远的节点的距离)。有M个询问,每个询问有一个Q值,求最多有多少个编号连续的节点可以满足其中的最大值和最小值的差不大于Q。

    题解:

    根据树直径的性质求出所有节点的权值,然后尺取法找答案就行了。

          

    代码

     
    #include<stdio.h>
    #include<math.h>
    const int N=5e4+1;
    int cnt,head[N],Ev[2*N],Ew[2*N],Enext[2*N],mm,vv;
    int dis[N],dpmax[N][20],dpmin[N][20];
    int mmax(int x,int y)
    {
        return x>y?x:y;
    }
    int mmin(int x,int y)
    {
        return x<y?x:y;
    }
    void addedge(int u,int v,int w)
    {
        Ev[cnt]=v;
        Ew[cnt]=w;
        Enext[cnt]=head[u];
        head[u]=cnt++;
    }
    void Dfs(int start,int id,int fa,int cost)
    {
        for(int i=head[id];i!=-1;i=Enext[i])
        {
            int v=Ev[i];
            int w=Ew[i];
            if(v==fa)continue;
            Dfs(start,v,id,cost+w);
        }
        if(cost>dis[id])dis[id]=cost;
        if(cost>mm&&id!=start)mm=cost,vv=id;
    }
    void clean(int n)
    {
       mm=0;
        for(int i=1;i<=n;++i)
        head[i]=-1,dis[i]=0;
        cnt=0;
    }
    void Make_Rmq(int n)
    {
        for(int i=1;i<=n;++i)
        {
            dpmax[i][0]=dis[i];
            dpmin[i][0]=dis[i];
        }
        for(int j=1;(1<<j)<=n;++j)
        for(int i=1;i+(1<<j)-1<=n;++i)
        {
            dpmax[i][j]=mmax(dpmax[i][j-1],dpmax[i+(1<<j-1)][j-1]);
            dpmin[i][j]=mmin(dpmin[i][j-1],dpmin[i+(1<<j-1)][j-1]);
        }
    }
    int Get_Rmq(int u,int v)
    {
        int k=0;  
        while((1<<(k+1))<=v-u+1)  
        k++;
        return mmax(dpmax[u][k],dpmax[v-(1<<k)+1][k])-mmin(dpmin[u][k],dpmin[v-(1<<k)+1][k]);
    }
    void solve()
    {
        int n,Q,x,y,z;
        while(~scanf("%d%d",&n,&Q)&&(n||Q))
        {
            clean(n);
            for(int i=1;i<n;++i)
            {
                scanf("%d%d%d",&x,&y,&z);
                addedge(x,y,z);
                addedge(y,x,z);
            }
            Dfs(1,1,1,0);
            x=vv;
            Dfs(x,x,x,0);
            y=vv;
            Dfs(y,y,y,0); 
            Make_Rmq(n);
            while(Q--)
            {
                scanf("%d",&x);
                vv=1;z=0;
                for(int i=1;i<=n;++i)
                {
                    while(vv<=i&&Get_Rmq(vv,i)>x)
                    vv++;
                    if(i-vv+1>z)z=i-vv+1;
                }
                printf("%d
    ",z);
            }
        }
    }
    int main()
    {
        solve();
        return 0;
    }

      

  • 相关阅读:
    MSSQL跨服务器插入
    TCP/IP详解 笔记一
    android学习十三 首选项
    android 学习十四 探索安全性和权限
    android学习十二 配置变化
    android学习十 ActionBar
    android学习十一 高级调试分析功能
    android学习九 对话框碎片
    android学习八 多用途碎片
    android学习七 菜单
  • 原文地址:https://www.cnblogs.com/kiuhghcsc/p/5734761.html
Copyright © 2011-2022 走看看