[JLOI2014]松鼠的新家【樹上差分】
阿新 • • 發佈:2018-12-17
Pro
Sol
很裸的一道樹上差分,不過和往常還不太一樣。
根據題目中給出的ai來差分,最後肯定有點被多加了值,所以最後再跑一邊去掉就好。
然而…… 我lca的模板打錯了……
Code
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; const long long L = 300005; struct Node { long long to , next; }; Node e[2*L]; long long n , q[L] , tot , head[L] , vis[L] , deep[L] , fa[L][35] , num[L]; void add(long long x , long long y) { tot++; e[tot].next = head[x]; e[tot].to = y; head[x] = tot; } void dfs(long long u) { vis[u] = 1; for(int i=head[u]; i; i=e[i].next) { long long v = e[i].to; if(vis[v]) continue; deep[v] = deep[u] + 1; fa[v][0] = u; dfs(v); } } long long lca(long long x , long long y) { if(deep[x]<deep[y]) swap(x,y); for(int i=30; i>=0; i--) if(deep[fa[x][i]]>=deep[y]) x = fa[x][i]; if(x==y) return x; for(int i=30; i>=0; i--) if(fa[x][i]!=fa[y][i]) x = fa[x][i] , y = fa[y][i]; return fa[x][0]; } void sol(long long l , long long r) { long long pa = lca(l,r); num[pa]--; num[fa[pa][0]]--; num[l]++; num[r]++; } void qans(long long u) { vis[u] = 1; for(int i=head[u]; i; i=e[i].next) { long long v = e[i].to; if(vis[v]) continue; qans(v); num[u] += num[v]; } } int main() { scanf("%lld",&n); for(int i=1; i<=n; i++) scanf("%lld",&q[i]); add(0 , 1); add(1 , 0); for(int i=1; i<n; i++) { long long x , y; scanf("%lld%lld",&x,&y); add(x , y); add(y , x); } dfs(0); for(int i=1; i<=30; i++) for(int j=1; j<=n; j++) fa[j][i] = fa[fa[j][i-1]][i-1]; for(int i=1; i<n; i++) { long long l = q[i] , r = q[i+1]; sol(l , r); } memset(vis , 0 , sizeof(vis)); qans(0); for(int i=2; i<=n; i++) num[q[i]]--; for(int i=1; i<=n; i++) printf("%lld\n",num[i]); return 0; }