bzoj 3631: [JLOI2014]松鼠的新家

来源:互联网 发布:owncloud源码分析 编辑:程序博客网 时间:2024/04/24 07:33

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


树链剖分的题目在win下跑总是爆栈导致没法debug..比较怨念。只能换到lemon下加编译命令测。

这题可以先树链剖分,然后路径区间加即可了。

#include<string>#include<cstdio>#include<cstring>#include<iostream>using namespace std;struct line{     int s,t;     int next;}a[600001];int edge;int head[300001];inline void add(int s,int t){ a[edge].next=head[s];     head[s]=edge;     a[edge].s=s;     a[edge].t=t;}struct tree{     int l,r;     int s;     int tag;}tr[1200001];inline int max(int x,int y){     if(x>y)          return x;     return y;}inline void up(int p){     tr[p].s=tr[p*2].s+tr[p*2+1].s;}inline void down(int p){ int l=tr[p].r-tr[p].l+1; tr[p*2].s+=(l-l/2)*tr[p].tag; tr[p*2+1].s+=l/2*tr[p].tag;     tr[p*2].tag+=tr[p].tag;     tr[p*2+1].tag+=tr[p].tag;     tr[p].tag=0;}inline void build(int p,int l,int r){     tr[p].l=l;     tr[p].r=r;     if(l!=r)     {          int mid=(l+r)/2;          build(p*2,l,mid);          build(p*2+1,mid+1,r);     }}inline void change(int p,int l,int r,int x)//单点修改 l==r 故未加tag操作 {     if(l<=tr[p].l&&tr[p].r<=r)     {          tr[p].s+=(tr[p].r-tr[p].l+1)*x;          tr[p].tag+=x;     }     else     {       down(p);      int mid=(tr[p].l+tr[p].r)/2;  if(l<=mid)       change(p*2,l,r,x);  if(r>mid)       change(p*2+1,l,r,x);  up(p);     }}inline int find(int p,int l,int r){     if(l<=tr[p].l&&tr[p].r<=r)          return tr[p].s;     else     {       down(p);      int mid=(tr[p].l+tr[p].r)/2;      int ans=0;  if(l<=mid)       ans+=find(p*2,l,r);  if(r>mid)       ans+=find(p*2+1,l,r);  return ans;     }}int dep[300001],size[300001],son[300001],fa[300001];int top[300001],w[300001];int lson[300001]/*最大节点位置*/,mson[300001]/*最大节点值*/;int tot;inline void dfs1(int d){     int i;     for(i=head[d];i!=0;i=a[i].next)     {       int t=a[i].t;          if(t!=fa[d])          {             dep[t]=dep[d]+1;               fa[t]=d;               dfs1(t);               son[d]+=son[t]+1;               if(son[t]>=mson[d])               {                    mson[d]=son[t];                    lson[d]=t;               }          }     }}inline void dfs2(int d){     int i;     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(t==lson[d])          {               top[t]=top[d];               tot++;               w[t]=tot;               dfs2(t);          }     }     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(t!=fa[d]&&t!=lson[d])          {               top[t]=t;               tot++;               w[t]=tot;               dfs2(t);          }     }}inline void addx(int s,int t){ int u=top[s],v=top[t];     while(u!=v)     {          if(dep[u]>dep[v])          {             change(1,w[u],w[s],1);               s=fa[top[s]];          }          else          {             change(1,w[v],w[t],1);               t=fa[top[t]];          }          u=top[s];          v=top[t];     }     if(w[s]<w[t])          change(1,w[s],w[t],1);     else          change(1,w[t],w[s],1);}int val[300001];int main(){//     freopen("home.in","r",stdin);//     freopen("home.out","w",stdout);     int n;     scanf("%d",&n);     int i,s,t;     for(i=1;i<=n;i++)          scanf("%d",&val[i]);     for(i=1;i<=n-1;i++)     {          scanf("%d%d",&s,&t);          edge++;          add(s,t);          edge++;          add(t,s);     }     dep[1]=1;     dfs1(1);     top[1]=1;     tot++;     w[1]=tot;     dfs2(1);     build(1,1,n);     for(i=1;i<=n-1;i++)     {          addx(val[i],val[i+1]);          if(i!=1)               change(1,w[val[i]],w[val[i]],-1);     }     change(1,w[val[n]],w[val[n]],-1);     for(i=1;i<=n;i++)          printf("%d\n",find(1,w[i],w[i]));     return 0;}


0 0
原创粉丝点击