luoguP3258 [JLOI2014]松鼠的新家

真搞不懂那些写树剖的人,放着60行的树上差分不写,写120左右树剖- -

树剖写的常数大还会T。。。差分稳如狗啊。

#include<bits/stdc++.h>
using namespace std;
const int maxn=300010;
int a[maxn],cnt=0,head[maxn],root=1,f[maxn][25],dep[maxn],cha[maxn];
struct edge{
    int to,next;
}e[maxn*2];
void add_edge(int s,int t){
    e[++cnt].next=head[s];e[cnt].to=t;head[s]=cnt;
    e[++cnt].next=head[t];e[cnt].to=s;head[t]=cnt;
}
void dfs(int u){
    for(int i=head[u];i;i=e[i].next){
        if(!dep[e[i].to]){
            dep[e[i].to]=dep[u]+1;
            f[e[i].to][0]=u;
            dfs(e[i].to);
        }
    }
}
void dfs2(int u){
    for(int i=head[u];i;i=e[i].next){
        if(dep[e[i].to]>dep[u]){
            dfs2(e[i].to);
            cha[u]+=cha[e[i].to];
        }
    }
}
int lca(int a,int b){
    if(dep[a]<dep[b])swap(a,b);
    for(int i=0;i<25;++i){
        if(((dep[a]-dep[b])>>i)&1)a=f[a][i];
    }
    if(a==b)return a;
    for(int i=24;i>=0;--i){
        if(f[a][i]!=f[b][i]){
            a=f[a][i];b=f[b][i];
        }
    }
    return f[a][0];
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    for(int i=1;i<=n-1;++i){
        int s,t;
        scanf("%d%d",&s,&t);
        add_edge(s,t);
    }
    dep[root]=1;
    dfs(root);
    for(int j=1;j<25;++j){
        for(int i=1;i<=n;++i){
            if(f[i][j-1])f[i][j]=f[f[i][j-1]][j-1];
        }
    }
    for(int i=1;i<n;++i){
        int l=lca(a[i],a[i+1]);
        cha[a[i]]++;cha[a[i+1]]++;cha[l]--;cha[f[l][0]]--;
    }
    dfs2(root);
    for(int i=2;i<=n;++i)cha[a[i]]--;
    for(int i=1;i<=n;++i)printf("%d\n",cha[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Dream-Runner/p/9415884.html