BZOJ 3631 松鼠的新家

来源:互联网 发布:双程网络剧百度云网盘 编辑:程序博客网 时间:2024/04/27 05:35

题意:
有一棵树,n个节点,从a1出发->a2->a3->…->an,(a为一个排列),每经过一个节点时,该节点加一,问最终每个节点的值


思路:
类似差分,lca(u,v)+1,u-1,v-1,从上往下统计答案就可以了

u+1,v+1,lca(u,v)-1,fa[lca[u,v]]-1,从下往上扫描


#include<cstdio>#include<algorithm>#include<queue>#include<cstring>using namespace std;const int N=3e5+100;const int DEG=20;struct Edge{    int to,next;}e[N*2];int a[N],ans[N],tot,head[N];void init(){    tot=0;    memset(head,-1,sizeof(head));}void addedge(int from,int to){    e[tot]=(Edge){to,head[from]};    head[from]=tot++;}int fa[N][DEG];int deg[N],degree[N];void bfs(int root){    queue<int>Q;    deg[root]=0;    fa[root][0]=0;    Q.push(root);    while(!Q.empty()){        int tmp=Q.front();        Q.pop();        for(int i=1;i<DEG;i++)            fa[tmp][i]=fa[fa[tmp][i-1]][i-1];        for(int i=head[tmp];i!=-1;i=e[i].next){            int v=e[i].to;            if(v==fa[tmp][0])   continue;            degree[tmp]++;            deg[v]=deg[tmp]+1;            fa[v][0]=tmp;            Q.push(v);        }    }}int LCA(int u,int v){    if(deg[u]>deg[v])   swap(u,v);    int tu=u,tv=v;    for(int det=deg[v]-deg[u],i=0;det;det>>=1,i++)        if(det&1)            tv=fa[tv][i];    if(tu==tv)  return tu;    for(int i=DEG-1;i>=0;i--){        if(fa[tu][i]==fa[tv][i])            continue;        tu=fa[tu][i],tv=fa[tv][i];    }    return fa[tu][0];}void get_ans(int n){    queue<int>Q;    for(int i=1;i<=n;i++)        if(degree[i]==0)            Q.push(i);    while(!Q.empty()){        int u=Q.front();        Q.pop();        for(int i=head[u];i!=-1;i=e[i].next){            int v=e[i].to;            if(v!=fa[u][0]) continue;            degree[v]--,ans[v]+=ans[u];            if(degree[v]==0)                Q.push(v);        }    }}int main(){    int n,u,v;    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]);    init();    for(int i=1;i<n;i++){        scanf("%d%d",&u,&v);        addedge(u,v),addedge(v,u);    }    bfs(1);    for(int i=2;i<=n;i++){        int lca=LCA(a[i],a[i-1]);        ans[ a[i-1] ]++,ans[ fa[a[i]][0] ]++;        ans[ fa[lca][0] ]--,ans[ lca ]--;    }    get_ans(n);    for(int i=1;i<=n;i++)        printf("%d\n",ans[i]);    return 0;}
0 0
原创粉丝点击