• #4259. 越野赛车问题


    题意
    内存限制:256 MiB
    时间限制:1000 ms
    小 $H$ 是一位优秀的越野赛车女选手。现在她准备在 $A$ 山上进行赛车训练。
    $A$ 山上一共有 $n$ 个广场,编号依次为 $1$ 到 $n$ ,这些广场之间通过 $n-1$条双向车道直接或间接地连接在一起。对于每条车道$i$ ,可以用四个正整数 $u_i,v_i,l_i,r_i$描述,表示车道连接广场 $u_i$ 和 $v_i$ ,其速度承受区间为$[l_i,r_i]$,即汽车必须以不小于$l_i$ 且不大于 $r_i$ 的速度经过车道$i$ 。
    小 $H$ 计划进行 $m$ 次训练,每次她需要选择 $A$ 山上的一条简单路径,然后在这条路径上行驶。但小 $H$ 不喜欢改变速度,所以每次训练时的车速都是固定的。
    现在小 $H$ 告诉你她在$m$ 次训练中计划使用的车速,请帮助她对于每次训练,找到一条合法的路径(车速在所有车道的速度承受区间的交集内),使得路径上经过的车道数最大。

    $1 leq n,m,l_i,r_i,v_i leq 70000$

    题解
    建一棵以速度为下标的线段树,把树上的每条边放到线段树中,然后对于询问进行线段树分治,每次走到一个区间就将里面的每条边的两个端点连成一个并查集,这个并查集要维护的信息是里面的点中的最长链,由于之后要撤销,所以不能路径压缩,改用启发式合并
    对于维护最长链,只需要将原来两个并查集的四个点拿出来,分别跑出路径大小,判断即可,这里需要用 $rmq$ 维护两点间的 $lca$

    代码

    #include <bits/stdc++.h>
    #define I inline
    using namespace std;const int N=70005;
    int n,m,t,f[N*2][18],c,d[N],fa[N],X[N],Y[N],L[N];
    int R[N],ans[N],sz[N],e[N],hd[N],V[N*2],nx[N*2];
    vector<int>g[N*4];struct O{int v,id;}p[N];struct far{int x,y;}h[N];
    struct E{int x,f,s;far k;};vector<E>a[N*4];
    I void add(int u,int v){V[++t]=v;nx[t]=hd[u];hd[u]=t;}
    I void dfs(int x,int F){
        f[++c][0]=x;d[x]=d[F]+1;e[x]=c;
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=F) dfs(V[i],x),f[++c][0]=x;
    }
    I int lca(int l,int r){
        if (l>r) swap(l,r);int i=log2(r-l+1);
        if (d[f[l][i]]<d[f[r-(1<<i)+1][i]])
            return f[l][i];return f[r-(1<<i)+1][i];
    }
    I bool cmp(O A,O B){return A.v<B.v;}
    I int get(int x){return x==fa[x]?x:get(fa[x]);}
    I int dis(int x,int y){return d[x]+d[y]-2*d[lca(e[x],e[y])];}
    #define Ls k<<1
    #define Rs k<<1|1
    #define mid ((l+r)>>1)
    I void update(int k,int l,int r,int ql,int qr,int v){
        if (ql<=l && r<=qr){g[k].push_back(v);return;}
        if (mid>=ql) update(Ls,l,mid,ql,qr,v);
        if (mid<qr) update(Rs,mid+1,r,ql,qr,v);
    }
    I void query(int k,int l,int r,int ql,int qr,int ax){
        for (int v,i=g[k].size()-1;~i;i--){
            v=g[k][i];int k1=get(X[v]),k2=get(Y[v]);
            if (sz[k1]<sz[k2]) swap(k1,k2);
            a[k].push_back((E){k2,k1,sz[k1],h[k1]});
            int T[2][2],now=0;
            T[0][0]=h[k1].x;T[0][1]=h[k1].y;
            T[1][0]=h[k2].x;T[1][1]=h[k2].y;
            for (int X1=0;X1<2;X1++) for (int Y1=0;Y1<2;Y1++)
            for (int X2=0;X2<2;X2++) for (int Y2=0;Y2<2;Y2++)
            if ((X1^X2) || (Y1^Y2)){
                int nw=dis(T[X1][Y1],T[X2][Y2]);
                if (nw>now) now=nw,h[k1]=(far){T[X1][Y1],T[X2][Y2]};
            }
            fa[k2]=k1;sz[k1]+=sz[k2];ax=max(ax,now);
        }
        if (l^r){
            int T=ql;for (;T<=qr;T++) if (p[T].v>mid) break;
            if (T>ql) query(Ls,l,mid,ql,T-1,ax);
            if (T<=qr) query(Rs,mid+1,r,T,qr,ax);
        }
        else for (int i=ql;i<=qr;i++) ans[p[i].id]=ax;
        for (int i=a[k].size()-1;~i;i--)
            sz[a[k][i].f]=a[k][i].s,h[a[k][i].f]=a[k][i].k,
            fa[a[k][i].x]=a[k][i].x;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for (int i=1;i<n;i++)
            scanf("%d%d%d%d",&X[i],&Y[i],&L[i],&R[i]),
            add(X[i],Y[i]),add(Y[i],X[i]),
            update(1,1,n,L[i],R[i],i);
        dfs(1,0);for (int i=c;i;i--)
            for (int j=1;i+(1<<j)<=c+1;j++){
                if (d[f[i][j-1]]<d[f[i+(1<<(j-1))][j-1]])
                    f[i][j]=f[i][j-1];
                else f[i][j]=f[i+(1<<(j-1))][j-1];
            }
        for (int i=1;i<=m;i++) scanf("%d",&p[i].v),p[i].id=i;
        for (int i=1;i<=n;i++) fa[i]=i,sz[i]=1,h[i]=(far){i,i};
        sort(p+1,p+m+1,cmp);query(1,1,n,1,m,0);
        for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    前天去游泳了
    Microsoft今天开了中文的MSDN了,以后查资料有时要快了点吧
    Visual Studio .NET已检测到指定的WEB服务运行的不是ASP.NET 1.1版
    sqlserver 2005 利用游标解决标量值函数主键自增id批量导入数据问题
    nvarchar查询条件中不用加单引号''吗?
    使用标量值函数作为主键自增值的时候,动软代码生成器的插入方法需要去掉主键的参数。
    c#里的'0','1'对应sqlserver2005中的False,True
    三元运算符绑定缩略内容
    循环插入数据存储过程
    01|02|03| ====> (01,02,03)用于in id数组这种查询方式
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10570902.html
Copyright © 2020-2023  润新知