BZOJ 3631 松鼠的新家

Posted on 2016-06-17 11:30  ziliuziliu  阅读(113)  评论(0编辑  收藏  举报

链剖。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 300500
#define maxe 600500
using namespace std;
int n,a[maxv],x,y,nume=0,g[maxv];
int w[maxv],fath[maxv],dis[maxv],son[maxv],size[maxv],top[maxv],tot=0;
int ls[maxv<<2],rs[maxv<<2],lazy[maxv<<2],root,cnt=0,ans[maxv];
struct edge
{
    int v,nxt;
}e[maxe];
void addedge(int u,int v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs1(int x)
{
    size[x]=1;son[x]=0;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (v!=fath[x])
        {
            fath[v]=x;
            dis[v]=dis[x]+1;
            dfs1(v);
            size[x]+=size[v];
            if (size[v]>size[son[x]]) 
                son[x]=v;    
        }
    }
}
void dfs2(int x,int father)
{
    top[x]=father;w[x]=++tot;
    if (son[x]) dfs2(son[x],father);
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if ((v!=fath[x]) && (v!=son[x]))
            dfs2(v,v);
    }
}
void build(int &now,int left,int right)
{
    now=++cnt;lazy[now]=0;
    if (left==right) return;
    int mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
}
void modify(int now,int left,int right,int l,int r)
{
    if ((left==l) && (right==r))
    {
        lazy[now]++;
        return;
    }
    int mid=(left+right)>>1;
    if (r<=mid) modify(ls[now],left,mid,l,r);
    else if (l>=mid+1) modify(rs[now],mid+1,right,l,r);
    else 
    {
        modify(ls[now],left,mid,l,mid);
        modify(rs[now],mid+1,right,mid+1,r);
    }
}
void work(int x)
{
    int p,q,f1,f2;
    p=a[x];q=a[x+1];
    f1=top[p];f2=top[q];
    while (f1!=f2)
    {
        if (dis[f1]<dis[f2]) 
        {
            swap(p,q);
            swap(f1,f2);
        }
        modify(root,1,n,w[f1],w[p]);
        p=fath[f1];f1=top[p];
    }
    if (dis[p]>dis[q]) swap(p,q);
    modify(root,1,n,w[p],w[q]);
}
int ask(int now,int left,int right,int p)
{
    if ((left==right) && (left==p))
        return lazy[now];
    int mid=(left+right)>>1;
    if (p<=mid) return ask(ls[now],left,mid,p)+lazy[now];
    else return ask(rs[now],mid+1,right,p)+lazy[now];
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for (int i=1;i<=n-1;i++)
    {
        scanf("%d%d",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    dfs1(1);
    dfs2(1,1);
    build(root,1,n);
    for (int i=1;i<=n-1;i++)
        work(i);
    for (int i=1;i<=n;i++)
    {
        int now=ask(root,1,n,w[a[i]]);
        if (i!=1) now--;
        ans[a[i]]=now;
    }
    for (int i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}