zoukankan      html  css  js  c++  java
  • HDU 4123(树上任意点到其他点的最远距离,rmq

    题目:求出一棵树上任意一点能到的最远距离,然后若干询问,问区间内最大最小距离只差小于q的区间最长有多长。

    思路:最远距离通过两次dfs树形dp求得,询问需要先用st表处理一下,然后线性扫。基本是参考kuangbin的。

    ps:可能是我写挫了。。用vector做邻接表是1996ms过了一次,然后就是无限tle。。。。不得不改成手写链表才搞到1500ms。。。vector感觉不能随便用了啊。。。。。。

    http://www.cnblogs.com/kuangbin/archive/2013/11/08/3414812.html

    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <functional>
    #include <set>
    #include <cmath>
    #define pb push_back
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps 0.0000000001
    #define IINF (1<<30)
    #define clr(x) memset((x),0,sizeof (x))
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=5e4+300;
    int N,M;
    struct EDGE{
        int t,d;
        EDGE *nt;
    }pool[maxv*3];
    int ph=0;
    EDGE *newedge(){
        pool[ph].nt=NULL;
        return &pool[ph++];
    }
    EDGE *head[maxv],*tail[maxv];
    int maxd[maxv],maxdn[maxv],smaxd[maxv],smaxdn[maxv];
    void addedge(int x,int y,int z){
        tail[x]->nt=newedge();
        tail[x]=tail[x]->nt;
        tail[x]->t=y,tail[x]->d=z;
    }
    void dfs1(int v,int fa){
        for(EDGE *i=head[v]->nt;i!=NULL;i=i->nt){
            int u=i->t;
            int len=i->d;
            if(u==fa) continue;
            dfs1(u,v);
            if(maxd[u]+len>smaxd[v]){
                smaxd[v]=maxd[u]+len;
                smaxdn[v]=u;
                if(smaxd[v]>maxd[v]){
                    swap(smaxd[v],maxd[v]);
                    swap(smaxdn[v],maxdn[v]);
                }
            }
        }
    }
    void dfs2(int v,int fa){
        for(EDGE *i=head[v]->nt;i!=NULL;i=i->nt){
            int u=i->t;
            int len=i->d;
            if(u==fa) continue;
            if(u==maxdn[v]){
                if(smaxd[v]+len>smaxd[u]){
                    smaxd[u]=smaxd[v]+len;
                    smaxdn[u]=v;
                    if(smaxd[u]>maxd[u]){
                        swap(smaxd[u],maxd[u]);
                        swap(smaxdn[u],maxdn[u]);
                    }
                }
            }else{
                if(maxd[v]+len>smaxd[u]){
                    smaxd[u]=maxd[v]+len;
                    smaxdn[u]=v;
                    if(smaxd[u]>maxd[u]){
                        swap(smaxd[u],maxd[u]);
                        swap(smaxdn[u],maxdn[u]);
                    }
                }
            }
            dfs2(u,v);
        }
    }
    ll STmin[maxv][30];
    ll STmax[maxv][30];
    void makeST(){
        memset(STmin,0x3f,sizeof STmin);
        memset(STmax,0,sizeof STmax);
        for(int i=1;i<=N;i++){
            STmin[i][0]=STmax[i][0]=maxd[i];
        }
        for(int k=1;k<25;k++){
            for(int i=1;i+(1<<k)<=N+1;i++){
                STmin[i][k]=min(STmin[i][k-1],STmin[i+(1<<(k-1))][k-1]);
                STmax[i][k]=max(STmax[i][k-1],STmax[i+(1<<(k-1))][k-1]);
            }
        }
    }
    int getdif(int l,int r){
        int k=0;
        while((1<<(k+1))<r-l) k++;
        return max(STmax[l][k],STmax[r-(1<<k)][k])-min(STmin[l][k],STmin[r-(1<<k)][k]);
    }
    void work(){
        clr(maxd);clr(maxdn);clr(smaxd);clr(smaxdn);
        dfs1(1,0);
        dfs2(1,0);
        makeST();
        while(M--){
            int Q;
            scanf("%d",&Q);
            int ans=0;
            int j=1;
            for(int i=1;i<=N;i++){
                while(j<=N&&getdif(i,j+1)<=Q){
                    j++;
                }
                ans=max(ans,j-i);
            }
            printf("%d
    ",ans);
        }
    
    }
    void init(){
        ph=0;
        for(int i=0;i<=N;i++){
            head[i]=newedge();
            head[i]->nt=NULL;
            tail[i]=head[i];
        }
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        /*    std::ios::sync_with_stdio(false);
            std::cin.tie(0);*/
        while(cin>>N>>M){
            if(N==0&&M==0) break;
            init();
            for(int i=0;i<N-1;i++){
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                addedge(x,y,z);
                addedge(y,x,z);
            }
            work();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    C#:基于WMI查询USB设备信息 及 Android设备厂商VID列表
    C#中 @ 的3种用途
    有关于 使用 命名管道 进行网络 进程间通信 的资料收集
    MySql LAST_INSERT_ID 【插入多条数据时】
    两个“不合理继承 ”的判定标识
    MYSQL 函数 字符串到整数
    Spring MVC 对于@ModelAttribute 、@SessionAttributes 的详细处理流程
    重构,拥有多个构造函数(重载)的类
    vue二级联动select
    gulp.dest用法详解
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4700852.html
Copyright © 2011-2022 走看看