BZOJ 3631 JLO2014 I松鼠的新家

3631: [JLOI2014]松鼠的新家

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2396  Solved: 1244
[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

利用树上差分,从x走到y可以看作x走到lca(x,y),再从lca(x,y)走到y
我们让x和y点的权值加1,lca(x,y)的权值-1,lca(x,y)的父节点的权值也减一
最后自下向上递归求出每一个点的权值,累加即可
#include <bits/stdc++.h>
using namespace std;
#define ll long long;
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1;  char ch=getc();
while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}
while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}
return x*f;
}
void put(int x){
if(x==0){
putchar('0');
putchar('
');
return;
}
if(x<0){
putchar('-');
x=-x;
}
int num=0;char ch[16];
while(x) ch[++num]=x%10+'0',x/=10;
while(num) putchar(ch[num--]);
putchar('
');
}
const int MAXN=500010;
namespace zhangenming{
 struct node{
  int y,next;
 }e[MAXN<<1];
 int linkk[MAXN<<1],fa[MAXN][30]={},len=0,n,a[MAXN],dep[MAXN],value[MAXN];
 inline void insert(int xx,int yy){
  e[++len].y=yy;e[len].next=linkk[xx];linkk[xx]=len;
 }
 void init(){
  n=read();
  for(int i=1;i<=n;i++){
   a[i]=read();
  }
  for(int i=1;i<n;i++){
   int xx=read();int yy=read();
   insert(xx,yy);
   insert(yy,xx);
  }
 }
 void dfs(int father,int st,int depth){
  fa[st][0]=father;dep[st]=depth;
  for(int i=linkk[st];i;i=e[i].next){
   if(e[i].y!=father){
    dfs(st,e[i].y,depth+1);
   }
  }
 }
 void getanser(){
  for(int i=1;i<=20;i++){
   for(int j=1;j<=n;j++){
    if(fa[j][i-1]!=0) fa[j][i]=fa[fa[j][i-1]][i-1];
    //cout<<fa[j][i]<<' ';
   }
  }
 }
 void dfs2(int st,int father){
  for(int i=linkk[st];i;i=e[i].next){
   if(e[i].y!=father){
    dfs2(e[i].y,st);
    value[st]+=value[e[i].y];
   }
  }
 }
 int LCA(int xx,int yy){
  if(xx==yy) return xx;
  if(dep[xx]<dep[yy]) swap(xx,yy);
  for(int i=20;i>=0;i--){
   if(dep[xx]-(1<<i)>=dep[yy]){
    xx=fa[xx][i];
   } 
  }
  if(xx==yy) return xx;
  for(int i=20;i>=0;i--){
   if(fa[xx][i]!=fa[yy][i]&&fa[xx][i]!=0){
    xx=fa[xx][i];yy=fa[yy][i];
   }
  }
  return fa[xx][0];
 }
 void print(){
  for(int i=1;i<=n;i++){
   put(value[i]);
  }
 }
 void solve(){
  dfs(0,1,0);
  getanser();
  for(int i=1;i<n;i++){
   int xx=a[i];int yy=a[i+1];
   int lca=LCA(xx,yy);
   value[xx]++;value[yy]++;value[lca]--;value[fa[lca][0]]--;
  }
  dfs2(1,0);
  for(int i=2;i<=n;i++){
   value[a[i]]--;
  }
 }
}
int main(){
 using namespace zhangenming;
 init();
 solve();
 print();
 return 0;
}

  

原文地址:https://www.cnblogs.com/something-for-nothing/p/7861568.html