BZOJ 3631 JLO2014 I松鼠的新家
3631: [JLOI2014]松鼠的新家
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
1 4 5 3 2
1 2
2 4
2 3
4 5
Sample Output
1
2
1
2
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('\n');
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('\n');
}
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;
}

浙公网安备 33010602011771号