[JLOI2014]松鼠的新家

3631: [JLOI2014]松鼠的新家

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1798  Solved: 875
[Submit][Status][Discuss]

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

Source

//树刨模板题 
#include<cstdio>
#include<algorithm>
#define lc k<<1
#define rc k<<1|1
using namespace std;
const int N=3e5+5;
struct edge{int v,next;}e[N<<1];int tot,head[N];
int n,m,dfs_cnt,fa[N],siz[N],son[N],dep[N],top[N],pos[N];
int a[N],s[N],sum[N<<2],tag[N<<2];
inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
    return x;
}
inline void add(int x,int y){
    e[++tot].v=y;e[tot].next=head[x];head[x]=tot;
    e[++tot].v=x;e[tot].next=head[y];head[y]=tot;
}
void dfs(int x,int f,int de){
    dep[x]=de;fa[x]=f;siz[x]=1;
    for(int i=head[x];i;i=e[i].next){
        if(e[i].v!=f){
            dfs(e[i].v,x,de+1);
            siz[x]+=siz[e[i].v];
            if(siz[son[x]]<siz[e[i].v]) son[x]=e[i].v;
        }
    }
}
void getpos(int x,int tp){
    top[x]=tp;pos[x]=++dfs_cnt;
    if(!son[x]) return ;
    getpos(son[x],tp);
    for(int i=head[x];i;i=e[i].next){
        if(e[i].v!=fa[x]&&e[i].v!=son[x]){
            getpos(e[i].v,e[i].v);
        }
    }
}
inline void updata(int k){
    sum[k]=sum[lc]+sum[rc];
}
inline void pushdown(int k,int l,int r){
    if(!tag[k]||l==r) return ;
    int mid=l+r>>1;
    tag[lc]+=tag[k];
    tag[rc]+=tag[k];
    sum[lc]+=tag[k]*(mid-l+1);
    sum[rc]+=tag[k]*(r-mid);
    tag[k]=0;
}
void change(int k,int l,int r,int x,int y,int val){
    pushdown(k,l,r);
    if(l==x&&r==y){
        tag[k]+=val;
        sum[k]+=val*(r-l+1);
        return ;
    }
    int mid=l+r>>1;
    if(y<=mid) change(lc,l,mid,x,y,val);
    else if(x>mid) change(rc,mid+1,r,x,y,val);
    else change(lc,l,mid,x,mid,val),change(rc,mid+1,r,mid+1,y,val);
    updata(k);
}
int query(int k,int l,int r,int x,int y){
    pushdown(k,l,r);
    if(l==x&&r==y) return sum[k];
    int mid=l+r>>1;
    if(y<=mid) return query(lc,l,mid,x,y);
    else if(x>mid) return query(rc,mid+1,r,x,y);
    else return query(lc,l,mid,x,mid)+query(rc,mid+1,r,mid+1,y);
    updata(k);
}
inline void vary(int x,int y){
    change(1,1,n,pos[y],pos[y],-1);
    for(;top[x]!=top[y];x=fa[top[x]]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        change(1,1,n,pos[top[x]],pos[x],1);
    }
    if(dep[x]>dep[y]) swap(x,y);
    change(1,1,n,pos[x],pos[y],1);
}
void reset(int k,int l,int r){
    if(l==r){
        s[l]=sum[k];return ;
    }
    pushdown(k,l,r);
    int mid=l+r>>1;
    reset(lc,l,mid);
    reset(rc,mid+1,r);
}
int main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1,x,y;i<n;i++) x=read(),y=read(),add(x,y);
    dfs(1,1,1);
    getpos(1,1);
    for(int i=1;i<n;i++) vary(a[i],a[i+1]);
    reset(1,1,n);
    for(int i=1;i<=n;i++) printf("%d
",s[pos[i]]); 
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/6426022.html