[JLOI2014]松鼠的新家

来源:互联网 发布:微信h5房卡牛牛源码 编辑:程序博客网 时间:2024/04/19 17:42

3631: [JLOI2014]松鼠的新家

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1736  Solved: 840

Description

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

Input

第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

Output

一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。

Sample Input

5
1 4 5 3 2
1 2
2 4
2 3
4 5

Sample Output

1
2
1
2
1

HINT

2<= n <=300000




思路:题意大致为在一棵树上进行一段段的点权值增加,有好多种方法可以解决,这里采用了树剖,同时用树状数组进行维护,直接进行最简单的区间修改,单点求值。


代码如下:

#include<cstdio>

#define N 300005

struct Node{
    int v,next;
}e[N*2];

int bl[N],pos[N],size[N],deep[N],fa[N],road[N],head[N],n,id,sz,c[N];

int read()
{
    int x=0,f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    return x*f;
}

void add(int u,int v) {e[id].v=v;e[id].next=head[u];head[u]=id++;}

void dfs1(int u)
{
    size[u]=1;
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].v;
        if (v==fa[u]) continue;
        deep[v]=deep[u]+1;fa[v]=u;
        dfs1(v);
        size[u]+=size[v];
    }
}

void dfs2(int u,int chain)
{
    int k=0;pos[u]=++sz;bl[u]=chain;
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].v;
        if (deep[v]>deep[u]&&size[v]>size[k]) k=v;
    }
    if (k==0) return;
    dfs2(k,chain);
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].v;
        if (deep[v]>deep[u]&&k!=v) dfs2(v,v);
    }
}

void swap(int &A,int &B) {int T=A;A=B;B=T;}

void Add(int x,int w) {for (;x<=n;x+=x&-x) c[x]+=w;}
int qry(int x) {int sm=0;for (;x;x-=x&-x) sm+=c[x];return sm;}

void insert(int x,int y)
{
    for (;bl[x]!=bl[y];)
    {
        if (deep[bl[x]]<deep[bl[y]]) swap(x,y);
        Add(pos[x]+1,-1);
        Add(pos[bl[x]],1);
        x=fa[bl[x]];
    }
    if (pos[x]>pos[y]) swap(x,y);
    Add(pos[y]+1,-1);
    Add(pos[x],1);
}

int main()
{
    n=read();id=1;sz=0;
    for (int i=1;i<=n;i++) road[i]=read();
    for (int i=1,u,v;i<n;i++) {u=read();v=read();add(u,v);add(v,u);}
    dfs1(1);dfs2(1,1);
    for (int i=1;i<n;i++)
        insert(road[i],road[i+1]);
    for (int i=1;i<=n;i++)
        if (i==road[1]) printf("%d\n",qry(pos[i]));else printf("%d\n",qry(pos[i])-1);
    return 0;
}


0 0
原创粉丝点击