ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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\n",ans);
    return 0;
}

 

posted on 2016-06-28 09:14  nul  阅读(320)  评论(0编辑  收藏  举报