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(' '); 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; }