zoukankan      html  css  js  c++  java
  • bzoj3910: 火车

    Description

    A 国有n 个城市,城市之间有一些双向道路相连,并且城市两两之间有唯一
    路径。现在有火车在城市 a,需要经过m 个城市。火车按照以下规则行驶:每次
    行驶到还没有经过的城市中在 m 个城市中最靠前的。现在小 A 想知道火车经过
    这m 个城市后所经过的道路数量。 

    Input

    第一行三个整数 n、m、a,表示城市数量、需要经过的城市数量,火车开始
    时所在位置。 
    接下来 n-1 行,每行两个整数 x和y,表示 x 和y之间有一条双向道路。 
    接下来一行 m 个整数,表示需要经过的城市。 

    Output

    一行一个整数,表示火车经过的道路数量。 
    树链剖分+树状数组维护每个点被经过了几次,然后就是模拟了
    #include<cstdio>
    const int M=30000000;
    char buf[M+4],*ptr=buf-1;
    inline int _int(){
        int x=0,c=*++ptr;
        while(c>57||c<48)c=*++ptr;
        while(c>47&&c<58)x=x*10+c-48,c=*++ptr;
        return x;
    }
    const int N=500010;
    int n,m,a;
    long long ans=0;
    int es[N*2],enx[N*2],e0[N],ep=2;
    int sz[N],son[N],top[N],fa[N],dep[N],id[N],bit[N],idp=0;
    void f1(int w,int pa){
        dep[w]=dep[pa]+1;
        sz[w]=1;
        fa[w]=pa;
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=pa){
                f1(u,w);
                sz[w]+=sz[u];
                if(sz[son[w]]<sz[u])son[w]=u;
            }
        }
    }
    void f2(int w,int tp){
        id[w]=++idp;
        top[w]=tp;
        if(son[w])f2(son[w],tp);
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=fa[w]&&u!=son[w])f2(u,u);
        }
    }
    void inc(int w,int v){
        while(w<=idp)bit[w]+=v,w+=w&-w;
    }
    int get(int w){
        int s=0;
        while(w)s+=bit[w],w-=w&-w;
        return s;
    }
    void lca(int x,int y){
        ans+=dep[x]+dep[y];
        int a=top[x],b=top[y],c;
        while(a!=b){
            if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c;
            inc(id[x]+1,-1);inc(id[a],1);
            x=fa[a];a=top[x];
        }
        if(dep[x]<dep[y]){
            ans-=dep[x]<<1;
            inc(id[x],1);inc(id[y]+1,-1);
        }else{
            ans-=dep[y]<<1;
            inc(id[y],1);inc(id[x]+1,-1);
        }
    }
    int main(){
        fread(buf,1,M,stdin);
        n=_int();m=_int();a=_int();
        for(int i=1;i<n;i++){
            int a=_int(),b=_int();
            es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
            es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
        }
        f1(1,0);f2(1,1);++idp;
        for(int i=0;i<m;i++){
            int x=_int();
            if(!get(id[x])){
                lca(a,x);
                a=x;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Mongodb---记一次事故故障
    扎克伯格的中文夜:想要成功就不能放弃
    TTS-零基础入门之停止列表中单条语音播报
    卡尔曼滤波(Kalman Filter) 的进一步讨论
    2014.8.12-AKKA和Actor model 分布式开发环境学习小结
    c# 删除程序占用的文件,强力删除文件,彻底删除文件,解除文件占用
    Spring源代码解析和配置文件载入
    java调用c++ dll出现中文乱码
    Android任务栈TaskStack
    应用中清理缓存应用实现
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5622248.html
Copyright © 2011-2022 走看看