bzoj 3631: [JLOI2014]松鼠的新家

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
#include
#include
#include
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]


你可能感兴趣的:(树链剖分,树链剖分)