From 0698b03d9454df405e0decbcfbd72520992203cb Mon Sep 17 00:00:00 2001 From: hanyixuanten Date: Thu, 29 Oct 2026 04:47:27 +0000 Subject: [PATCH] new file: P3258.cpp --- P3258.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ P3258.md | 48 +++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 P3258.cpp create mode 100644 P3258.md diff --git a/P3258.cpp b/P3258.cpp new file mode 100644 index 0000000..8e30a2e --- /dev/null +++ b/P3258.cpp @@ -0,0 +1,99 @@ +#include +#define int long long +using namespace std; +int n; +int a[300005]; +int fa[300005]; +int dfn[300005]; +int son[300005]; +int dep[300005]; +int top[300005]; +int cnt[300005]; +vector fri[300005]; +int dfnnow; +struct SEG{ + int num[1200005], lt[1200005]; + void pu(int now) { + num[now] = num[now * 2] + num[now * 2 + 1]; + } + void pd(int now, int nl, int nr) { + int nmid = (nl + nr) >> 1, l = lt[now]; + num[now * 2] += l * (nmid - nl + 1); + num[now * 2 + 1] += l * (nr - nmid); + lt[now * 2] += l; + lt[now * 2 + 1] += l; + lt[now] = 0; + } + void add(int now, int nl, int nr, int l, int r, int nn) { + if(nr < l || nl > r) return; + if(l <= nl && nr <= r) { + num[now] += (nr - nl + 1) * nn; + lt[now] += nn; + return; + } + int nmid = (nl + nr) >> 1; + pd(now, nl, nr); + add(now * 2, nl, nmid, l, r, nn); + add(now * 2 + 1, nmid + 1, nr, l, r, nn); + pu(now); + } + int query(int now, int nl, int nr, int l, int r) { + if(nr < l || nl > r) return 0; + if(l <= nl && nr <= r) { + return num[now]; + } + int nmid = (nl + nr) >> 1; + pd(now, nl, nr); + return query(now * 2, nl, nmid, l, r) + query(now * 2 + 1, nmid + 1, nr, l, r); + } +}seg; +void dfs1(int now, int from) { + cnt[now] = 1; + for(int i : fri[now]) { + if(i == from) continue; + fa[i] = now; + dep[i] = dep[now] + 1; + dfs1(i, now); + cnt[now] += cnt[i]; + if(cnt[son[now]] < cnt[i]) son[now] = i; + } +} +void dfs2(int now, int from) { + top[now] = from; + dfn[now] = ++dfnnow; + if(son[now]) dfs2(son[now], from); + for(int i : fri[now]) { + if(i == fa[now] || i == son[now]) continue; + dfs2(i, i); + } +} +void edit(int a, int b, int nn = 1) { + while(top[a] != top[b]) { + if(dep[top[a]] < dep[top[b]]) swap(a, b); + seg.add(1, 1, n, dfn[top[a]], dfn[a], nn); + a = fa[top[a]]; + } + if(dep[a] < dep[b]) swap(a, b); + seg.add(1, 1, n, dfn[b], dfn[a], nn); +} +signed main() { + scanf("%lld", &n); + for(int i = 1; i <= n; ++i) { + scanf("%lld", &a[i]); + } + for(int i = 1, u, v; i < n; ++i) { + scanf("%lld%lld", &u, &v); + fri[u].push_back(v); + fri[v].push_back(u); + } + dfs1(1, -1); + dfs2(1, 1); + for(int i = 1; i < n; ++i) { + edit(a[i], a[i + 1]); + edit(a[i + 1], a[i + 1], -1); + } + for(int i = 1; i <= n; ++i) { + printf("%lld\n", seg.query(1, 1, n, dfn[i], dfn[i])); + } + return 0; +} \ No newline at end of file diff --git a/P3258.md b/P3258.md new file mode 100644 index 0000000..9fd6903 --- /dev/null +++ b/P3258.md @@ -0,0 +1,48 @@ +# P3258 [JLOI2014] 松鼠的新家 + +## 题目描述 + +松鼠的新家是一棵树,前几天刚刚装修了新家,新家有 $n$ 个房间,并且有 $n-1$ 根树枝连接,每个房间都可以相互到达,且两个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。 + +松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去 $a_1$,再去 $a_2$,……,最后到 $a_n$,去参观新家。可是这样会导致重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。 + +维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。 + +因为松鼠参观指南上的最后一个房间 $a_n$ 是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。 + +## 输入格式 + +第一行一个正整数 $n$,表示房间个数。第二行 $n$ 个正整数,依次描述 $a_1, a_2,\cdots,a_n$。 + +接下来 $n-1$ 行,每行两个正整数 $x,y$,表示标号 $x$ 和 $y$ 的两个房间之间有树枝相连。 + +## 输出格式 + +一共 $n$ 行,第 $i$ 行输出标号为 $i$ 的房间至少需要放多少个糖果,才能让维尼有糖果吃。 + +## 输入输出样例 #1 + +### 输入 #1 + +``` +5 +1 4 5 3 2 +1 2 +2 4 +2 3 +4 5 +``` + +### 输出 #1 + +``` +1 +2 +1 +2 +1 +``` + +## 说明/提示 + +对于全部的数据,$2 \le n \le 3 \times 10^5$,$1 \le a_i \le n$。 \ No newline at end of file