1 条题解
-
0
自动搬运
来自洛谷,原作者为

Egg_eating_master
Always break; Never continue; | 我吃了个蛋搬运于
2025-08-24 23:11:05,当前版本为作者最后更新于2025-03-16 20:46:11,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
考虑对区间的包含关系建树。在这棵树上,从 走到 相当于走到当前节点子树内 dfn 的最大值 的位置,从 走到 相当于走到当前节点的第一个儿子。
现在我们可以刻画从 到 的距离了,它是这样一个东西:从 到 的路径上所有点的右兄弟数量之和,加上从 到 的路径上所有点的左兄弟数量之和。
记 表示从 到根的路径上所有点的右兄弟数量之和, 表示左兄弟数量之和, 表示兄弟数量之和,那么从 到 的距离就是 。然后就可以直接上 dsu 了。
时间复杂度 。
#include<bits/stdc++.h> #define int long long using namespace std; const int maxn = 300005; int n, m; int v[maxn]; int a[maxn], b[maxn], c[maxn]; int sz[maxn], son[maxn]; vector<int> s[maxn]; vector<int> d[maxn]; vector<int> tmp; stack<int> st; int ans[maxn]; struct BIT { int sum[maxn]; int lowbit(int x) {return x & -x;} void update(int x, int val) {for (; x <= n + 1; x += lowbit(x)) sum[x] += val;} int query(int x) {int res = 0; for (; x > 0; x -= lowbit(x)) res += sum[x]; return res;} } t1, t2; void build() { st.push(0); for (int i = 1; i <= n; i++) { while (v[st.top()] < v[i]) st.pop(); d[st.top()].push_back(i); st.push(i); } } void dfs1(int x) { sz[x] = 1; for (int i = 0; i < d[x].size(); i++) { int y = d[x][i]; a[y] = a[x] + d[x].size() - i - 1, b[y] = b[x] + i + 1; c[y] = c[x] + d[y].size(); dfs1(y); sz[x] += sz[y]; if (son[x] == 0 || sz[y] > sz[son[x]]) son[x] = y; } } void clear(int x) { if (x) t1.update(b[x], -1); for (auto y : d[x]) clear(y); } void heige(int x) { tmp.push_back(x); for (auto y : d[x]) heige(y); } void dfs2(int x) { if (son[x] == 0) {t1.update(b[x], 1); return;} for (auto y : d[x]) if (y != son[x]) {dfs2(y); clear(y);} dfs2(son[x]); vector<int> f; int p = 0; for (int i = d[x].size() - 1; i >= 0; i--) { int y = d[x][i]; if (y == son[x]) {p = i; break;} tmp.clear(); heige(y); for (auto j : tmp) ans[j] += t2.query(min(m - a[j] + c[x], n + 1)); for (auto j : tmp) t2.update(b[j], 1), s[son[x]].push_back(m - b[j] + c[x]), f.push_back(j); } for (auto y : f) t2.update(b[y], -1), t1.update(b[y], 1); for (int i = p - 1; i >= 0; i--) { int y = d[x][i]; tmp.clear(); heige(y); for (auto j : tmp) ans[j] += t1.query(min(m - a[j] + c[x], n + 1)); for (auto j : tmp) t1.update(b[j], 1); } ans[x] += t1.query(min(m + b[x], n + 1)); if (x) t1.update(b[x], 1); } void dfs3(int x) { for (auto i : s[x]) if (i >= 0) t2.update(min(i + 1, n + 1), 1); ans[x] += t2.query(n + 1) - t2.query(a[x]); for (auto y : d[x]) dfs3(y); for (auto i : s[x]) if (i >= 0) t2.update(min(i + 1, n - 1), -1); } signed main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> n >> m; for (int i = 1; i < n; i++) cin >> v[i]; v[n] = n + 1, v[0] = n + 2; build(); c[0] = d[0].size(); dfs1(0); dfs2(0); dfs3(0); for (int i = 1; i <= n; i++) cout << ans[i] + 1 << ' '; cout << '\n'; return 0; }
- 1
信息
- ID
- 11708
- 时间
- 1200ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者