专栏文章
【P12645 [KOI 2024 R1] 二叉树】题解
P12645题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mip62vol
- 此快照首次捕获于
- 2025/12/03 06:45 3 个月前
- 此快照最后确认于
- 2025/12/03 06:45 3 个月前
记号与约定
- 题面中提到的,若无特殊说明,均与题面一致;
- :;
- : 所包含的叶子节点数;
- : 中 ;
- : 中 ;
思路
一眼树形 DP。
在一棵子树 中,类似 CDQ 分治地,我们可以把需要处理的 分为三类:
在一棵子树 中,类似 CDQ 分治地,我们可以把需要处理的 分为三类:
- 完全在左子树 中的;
- 完全在右子树 中的;
- 一部分在 中,一部分在 中的。
前两种情况在 和 中已经处理过了,因此只需要处理第三种。
观察发现,在第三种情况中,除了 外,剩下的都满足 ,即左子树中的 后缀和加上右子树中的 前缀和。
观察发现,在第三种情况中,除了 外,剩下的都满足 ,即左子树中的 后缀和加上右子树中的 前缀和。
以下令
于是我们能够得到: 现在的问题在于如何快速计算后面三项。
注意到 ,于是有:
于是我们能够得到: 现在的问题在于如何快速计算后面三项。
注意到 ,于是有:
接下来的问题就是如何通过左右子树的 推出 。
先看 。注意到 ,则只需考虑 范围内的叶子节点。我们发现这些叶子节点的前缀 其实就是其在 的前缀 再加上一整颗左子树。于是有: 同理:
先看 。注意到 ,则只需考虑 范围内的叶子节点。我们发现这些叶子节点的前缀 其实就是其在 的前缀 再加上一整颗左子树。于是有: 同理:
剩下的信息就很好求了。
初始化 。
同时。
初始化 。
同时。
时间复杂度
。
AC Code
CPP#include <bits/stdc++.h>
#define UP(i, l, r) for(int i = (l); i <= (r); ++ i)
#define DN(i, l, r) for(int i = (r); i >= (l); -- i)
#define LUP(i, l, r) for(ll i = (l); i <= (r); ++ i)
#define LDN(i, l, r) for(ll i = (r); i >= (l); -- i)
#define FE(i, s) for(auto i : s)
#define PB push_back
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using vi = vector<int>;
const int INF = 0x3f3f3f3f, INFB = 0x3f, N = 1e5, MOD = 1e9 + 7;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
int n, a[N + 5], b[N + 5];
ll dp[N + 5], nl[N + 5], sf[N + 5], pr[N + 5];
bitset<N + 5> ir, vis;
ll md(ll x){ return (x % MOD + MOD) % MOD; }
void dfs(int u){
if(!vis[a[u]]){
dfs(a[u]);
vis.set(a[u]);
}
if(!vis[b[u]]){
dfs(b[u]);
vis.set(b[u]);
}
nl[u] = md(nl[a[u]] + nl[b[u]]);
sf[u] = md(md(sf[a[u]] + nl[a[u]]) + sf[b[u]] - 1);
pr[u] = md(md(pr[b[u]] + nl[b[u]]) + pr[a[u]] - 1);
dp[u] = md(md(md(dp[a[u]] + dp[b[u]]) + md(nl[b[u]] * sf[a[u]])) + md(md(nl[a[u]] * pr[b[u]]) - 1));
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
dp[0] = nl[0] = sf[0] = pr[0] = 1;
ir.set();
vis.set(0);
UP(i, 1, n){
cin >> a[i] >> b[i];
ir.reset(a[i]);
ir.reset(b[i]);
}
UP(i, 1, n) if(ir[i]) dfs(i);
UP(i, 1, n) cout << dp[i] << endl;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...