zoukankan      html  css  js  c++  java
  • 树形DP+RMQ+单调队列(Bob’s Race HDU4123)

    题意:有n个房子,这些房子被n-1条道路连接,有一些运动员从一个房子为起点尽可能跑最远的距离且不能通过一条道路超过两次,这些运行员不能选择同样的起点,这些运动员跑的最远距离和最近距离的差值不能超过Q,这些运行员的起点房间编号都是连续的,问最多可以选择多少个运动员跑步?

    分析:就是给出一颗树形图,先用dp求出每个点所能经过的最远距离,然后用rmq求区间最值,最后用单调队列询问结果(n)的复杂度

    #include"stdio.h"
    #include"string.h"
    #include"stdlib.h"
    #include"queue"
    #include"algorithm"
    #include"string.h"
    #include"string"
    #include"math.h"
    #include"vector"
    #include"stack"
    #include"map"
    #define eps 1e-4
    #define inf 10000000
    #define M 50009
    #define PI acos(-1.0)
    using namespace std;
    struct node
    {
        int u,v,w,next;
    }edge[M*2];
    int t,head[M],belong[M],dis[M][4],Log[M];
    int dp_max[M][17],dp_min[M][17];//注意第二维的数组大小,太大会超时
    void init()
    {
        t=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w)
    {
        //edge[t].u=u;
        edge[t].v=v;
        edge[t].w=w;
        edge[t].next=head[u];
        head[u]=t++;
    }
    void dfs(int u,int f)
    {
        dis[u][0]=dis[u][1]=dis[u][2]=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(v==f)continue;
            dfs(v,u);
            if(dis[u][0]<dis[v][0]+edge[i].w)
            {
                dis[u][1]=dis[u][0];
                dis[u][0]=dis[v][0]+edge[i].w;
                belong[u]=v;
            }
            else if(dis[u][1]<dis[v][0]+edge[i].w)
                dis[u][1]=dis[v][0]+edge[i].w;
        }
    }
    void dfs1(int u,int f)
    {
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            if(v==f)continue;
            if(v==belong[u])
                dis[v][2]=max(dis[u][1],dis[u][2])+edge[i].w;
            else
                dis[v][2]=max(dis[u][0],dis[u][2])+edge[i].w;
            dfs1(v,u);
        }
    }
    void RMQ(int n)
    {
        int i,j;
        int m=Log[n];
        for(i=1;i<=n;i++)
            dp_min[i][0]=dp_max[i][0]=dis[i][3];
        for(j=1;j<=m;j++)
        {
            for(i=1;i<=n+1-(1<<j);i++)
            {
                dp_max[i][j]=max(dp_max[i][j-1],dp_max[i+(1<<(j-1))][j-1]);
                dp_min[i][j]=min(dp_min[i][j-1],dp_min[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int lcp(int x,int y)
    {
        int m=Log[y-x+1];
        return max(dp_max[x][m],dp_max[y+1-(1<<m)][m])-min(dp_min[x][m],dp_min[y+1-(1<<m)][m]);
    }
    int main()
    {
        int n,m,i,a,b,c;
        Log[0] = -1;
        for(int i = 1;i <M;i++)
            Log[i] = ((i&(i-1)) == 0)?Log[i-1]+1:Log[i-1];
        while(scanf("%d%d",&n,&m),m||n)
        {
            init();
            for(i=1;i<n;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c);
                add(b,a,c);
            }
            dfs(1,-1);
            dfs1(1,-1);
            for(i=1;i<=n;i++)
            {
                dis[i][3]=max(dis[i][0],dis[i][2]);
                //printf("%d
    ",dis[i][3]);
            }
            RMQ(n);
            for(i=1;i<=m;i++)
            {
                int Q;
                scanf("%d",&Q);
                int l,r;
                l=r=1;
                int ans=0;
                while(r<=n)
                {
                    int cha=lcp(l,r);
                    if(cha<=Q)
                    {
                        ans=max(ans,r-l+1);
                        r++;
                    }
                    else
                        l++;
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    


  • 相关阅读:
    统一回复《怎么学JavaScript?》
    nodejs配置简单HTTP服务器
    web跨域解决方案
    JavaScript 调试小技巧
    我从编程总结的 22 个经验
    Sublime Text 3103 Crack 破解 注册码(亲测有效)
    mstsc 远程序桌面登录的 c#开发
    突然顿悟的Javascript中的this
    解决Electron加载带jquery的项目报错问题
    ES6+ 开发 React 组件
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348111.html
Copyright © 2011-2022 走看看