zoukankan      html  css  js  c++  java
  • Dash Speed

    题目大意:

    比特山是比特镇的飙车圣地。在比特山上一共有n 个广场,编号依次为1 到n,这些广场之间通过n - 1 条双向车道直接或间接地连接在一起,形成了一棵树的结构。
    因为每条车道的修建时间以及建筑材料都不尽相同,所以可以用两个数字li; ri 量化地表示一条车道的承受区间,只有当汽车以不小于li 且不大于ri 的速度经过这条车道时,才不会对路面造成伤害。
    Byteasar 最近新买了一辆跑车,他想在比特山飙一次车。Byteasar 计划选择两个不同的点S; T,然后在它们树上的最短路径上行驶,且不对上面任意一条车道造成伤害。
    Byteasar 不喜欢改变速度,所以他会告诉你他的车速。为了挑选出最合适的车速,Byteasar 一共会向你询问m 次。请帮助他找到一条合法的道路,使得路径上经过的车道数尽可能多。

    数据范围n,m<=70000.

    题解:

    (蒟蒻眼中)比较神的树上分治。做法分治[ l , r ] :(丑图奉上)

    其中每一个矩形代表分治区间,圆代表提取答案的地方。

    每当访问到矩形/圆时,将对应区间加的边更新并查集,然后不断用新集的直径更新当前答案。

    (ps.当两棵树合并时,新树的直径一定在旧树的端点中产生。这里需要6次特判。)

    每当返回时,将原来的更新取消。可以先记录栈的tl,然后将栈还原。

    细节比较多,详细见代码:


    upd:由于之前代码太丑被和谐,附上新代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 70050;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n,m,hed[N],cnt,dep[N],siz[N],fa[N],son[N],tp[N];
    struct EG
    {
        int to,nxt;
    }e[N<<1];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    void dfs1(int u,int f)
    {
        fa[u]=f,dep[u]=dep[f]+1,siz[u]=1;
        for(int j=hed[u],to;j;j=e[j].nxt)
            if((to=e[j].to)!=f)
            {
                dfs1(to,u),siz[u]+=siz[to];
                if(siz[son[u]]<siz[to])son[u]=to;
            }
    }
    void dfs2(int u,int Top)
    {
        tp[u] = Top;
        if(!son[u])return ;
        dfs2(son[u],Top);
        for(int j=hed[u],to;j;j=e[j].nxt)if((to=e[j].to)!=fa[u]&&to!=son[u])
            dfs2(to,to);
    }
    int get_lca(int x,int y)
    {
        while(tp[x]!=tp[y])
        {
            if(dep[tp[x]]<dep[tp[y]])swap(x,y);
            x = fa[tp[x]];
        }
        return dep[x]<dep[y]?x:y;
    }
    int get_dis(int x,int y){return dep[x]+dep[y]-2*dep[get_lca(x,y)];}
    struct Tree
    {
        int a,b,w;
        Tree(){}
        Tree(int a,int b,int w):a(a),b(b),w(w){}
        Tree operator + (const Tree&x)const
        {
            Tree ret = Tree(a,b,w);int tmp;
            if(ret.w<x.w)ret=x;
            tmp=get_dis(a,x.a);if(ret.w<tmp)ret=Tree(a,x.a,tmp);
            tmp=get_dis(a,x.b);if(ret.w<tmp)ret=Tree(a,x.b,tmp);
            tmp=get_dis(b,x.a);if(ret.w<tmp)ret=Tree(b,x.a,tmp);
            tmp=get_dis(b,x.b);if(ret.w<tmp)ret=Tree(b,x.b,tmp);
            return ret;
        }
    };
    int ans[N];
    struct segtree
    {
        struct point
        {
            Tree s;
            int ff,siz;
        }p[N];
        struct node
        {
            int u;point p0;
            node(){}
            node(int u,point p0):u(u),p0(p0){}
        }sta[N<<5];
        int hd[N<<2],ct,tl;
        struct edge
        {
            int u,v,nxt;
        }E[N<<5];
        void ae(int f,int u,int v)
        {
            E[++ct].u = u;
            E[ct].v = v;
            E[ct].nxt = hd[f];
            hd[f] = ct;
        }
        void insert(int l,int r,int u,int ql,int qr,int&lp,int&rp)
        {
            if(l==ql&&r==qr){ae(u,lp,rp);return ;}
            int mid = (l+r)>>1;
            if(qr<=mid)insert(l,mid,u<<1,ql,qr,lp,rp);
            else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,lp,rp);
            else insert(l,mid,u<<1,ql,mid,lp,rp),insert(mid+1,r,u<<1|1,mid+1,qr,lp,rp);
        }
        int findff(int u){return u==p[u].ff?u:findff(p[u].ff);}
        void merge(int u,int v,int&now)
        {
            u = findff(u),v = findff(v);
            if(u==v)return ;
            if(p[u].siz>p[v].siz)swap(u,v);
            sta[++tl]=node(u,p[u]),sta[++tl]=node(v,p[v]);
            p[v].s=p[v].s+p[u].s,p[u].ff=v;
            if(p[u].siz==p[v].siz)p[v].siz++;
            now = max(now,p[v].s.w);
        }
        void rep(int las)
        {
            while(tl!=las)p[sta[tl].u]=sta[tl].p0,tl--;
        }
        void sol(int l,int r,int u,int now)
        {
            int tim = tl;
            for(int j=hd[u];j;j=E[j].nxt)
                merge(E[j].u,E[j].v,now);
            if(l==r){ans[l]=now;rep(tim);return ;}
            int mid = (l+r)>>1;
            sol(l,mid,u<<1,now);sol(mid+1,r,u<<1|1,now);
            rep(tim);
        }
    }tr;
    int main()
    {
    //    freopen("tt.in","r",stdin);
        read(n),read(m);
        for(int u,v,l,r,i=1;i<n;i++)
        {
            read(u),read(v),read(l),read(r);
            ae(u,v),ae(v,u);tr.insert(1,n,1,l,r,u,v);
        }
        dfs1(1,0),dfs2(1,1);
        for(int i=1;i<=n;i++)
            tr.p[i].ff=i,tr.p[i].siz=1,tr.p[i].s=Tree(i,i,0);
        tr.sol(1,n,1,0);
        for(int i=1,x;i<=m;i++)
            read(x),printf("%d
    ",ans[x]);
        return 0;
    }
    View Code
  • 相关阅读:
    Visual Studio 2008 可扩展性开发(一):VS概览
    CButtonST使用技巧: CButtonST简介
    Doxygen + Graphviz + Htmlhelp, 成为文档好手
    Django的多数据库处理(垂直分库和水平分库)
    赫曼米勒中国| 设计,让世界更美好。
    maccman/juggernaut
    aptget y install buildessential
    QT分析之WebKit(三)
    Django的多数据库支持,太酷了~
    我们的征途是星辰大海#
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9863159.html
Copyright © 2011-2022 走看看