1. 程式人生 > >[Luogu] P3258 [JLOI2014]松鼠的新家

[Luogu] P3258 [JLOI2014]松鼠的新家

const 都是 ostream spa top roo ++ int +=

題目描述

松鼠的新家是一棵樹,前幾天剛剛裝修了新家,新家有n個房間,並且有n-1根樹枝連接,每個房間都可以相互到達,且倆個房間之間的路線都是唯一的。天哪,他居然真的住在”樹“上。

松鼠想邀請小熊維尼前來參觀,並且還指定一份參觀指南,他希望維尼能夠按照他的指南順序,先去a1,再去a2,......,最後到an,去參觀新家。可是這樣會導致維尼重復走很多房間,懶惰的維尼不停地推辭。可是松鼠告訴他,每走到一個房間,他就可以從房間拿一塊糖果吃。

維尼是個饞家夥,立馬就答應了。現在松鼠希望知道為了保證維尼有糖果吃,他需要在每一個房間各放至少多少個糖果。

因為松鼠參觀指南上的最後一個房間an是餐廳,餐廳裏他準備了豐盛的大餐,所以當維尼在參觀的最後到達餐廳時就不需要再拿糖果吃了。

題目分析

樹剖,樹狀數組維護

相鄰兩個計劃點之間的點權++,第2~n個計劃點點權-1。

Code

#include<iostream>
#include<cstdio>
using namespace std;

const int MAXN = 300000 + 5;

struct Edge {
    int nxt;
    int to;
} l[MAXN<<1];

int n,root;
int head[MAXN],cnt;
int deep[MAXN],fa[MAXN],siz[MAXN],heavy[MAXN];
int id[MAXN],tot; int a[MAXN],c[MAXN],top[MAXN]; inline void add(int x,int y) { cnt++; l[cnt].nxt = head[x]; l[cnt].to = y; head[x] = cnt; return; } void dfs1(int x,int from) { deep[x] = deep[from] + 1; fa[x] = from; int tmp = 0; siz[x] = 1; for
(int i = head[x];i;i = l[i].nxt) { if(l[i].to == from) continue; dfs1(l[i].to,x); siz[x] += siz[l[i].to]; if(siz[l[i].to] > tmp) { tmp = siz[l[i].to]; heavy[x] = l[i].to; } } return; } void dfs2(int x,int tp,int from) { id[x] = ++tot; top[x] = tp; if(!heavy[x]) return; dfs2(heavy[x],tp,x); for(int i = head[x];i;i = l[i].nxt) { if(l[i].to == from || l[i].to == heavy[x]) continue; dfs2(l[i].to,l[i].to,x); } return; } inline int lowbit(int x) { return x & (-x); } inline void modify(int x,int y,int v) { for(int i = x;i <= n;i += lowbit(i)) c[i]+=v; for(int i = y+1;i <= n;i += lowbit(i)) c[i]-=v; return; } inline int query(int x) { int res = 0; for(int i = x;i;i -= lowbit(i)) res += c[i]; return res; } inline void wayadd(int x,int y,int v) { while(top[x] != top[y]) { if(deep[top[x]] < deep[top[y]]) swap(x,y); modify(id[top[x]],id[x],v); x = fa[top[x]]; } if(deep[x] > deep[y]) swap(x,y); modify(id[x],id[y],v); return; } int main() { scanf("%d",&n); for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); } root = a[1]; int x,y; for(int i = 1;i < n;i++) { scanf("%d%d",&x,&y); add(x,y);add(y,x); } dfs1(root,0); dfs2(root,root,0); for(int i = 1;i < n;i++) { wayadd(a[i],a[i+1],1); wayadd(a[i+1],a[i+1],-1); } for(int i = 1;i <= n;i++) { printf("%d\n",query(id[i])); } return 0; }

[Luogu] P3258 [JLOI2014]松鼠的新家