CF1930G
考虑 dp,设
考虑转移
-
-
对于
\operatorname{LCA}(i,j) 朝i 方向的子树,显然i 一定是这个子树里面的最大值。
直接做是
对于祖先的贡献:若
对于祖先其他子树
做到了
:::success[Code]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
const int N = 1e6 + 7;
const int mod = 998244353;
int n, f[N], mx[N], t[N], c[N];
vector<int> e[N];
inline int lowbit(int x)
{
return x & (-x);
}
inline void update(int i, int C)
{
for (; i <= n; i += lowbit(i))
c[i] += C;
return;
}
inline int query(int i)
{
if(i<=0)return 0ll;
int res = 0;
for (; i; i -= lowbit(i))
res += c[i];
return res;
}
inline void dfs1(int u, int fa)
{
mx[u] = u, t[u] = max(t[fa], fa);
for (auto v : e[u])
if (v != fa)
dfs1(v, u), mx[u] = max(mx[u], mx[v]);
sort(e[u].begin(), e[u].end(), [&](const int &x, const int &y)
{ return mx[x] < mx[y]; });
}
inline void dfs2(int u, int fa)
{
if (t[u] > u)
f[u] = 0;
else
f[u] = max(1ll, f[t[u]] + query(u - 1) - query(t[u] - 1)) % mod;
for (auto v : e[u])
if (v != fa)
dfs2(v, u), update(mx[v], f[mx[v]]);
for (auto v : e[u])
if (v != fa)
update(mx[v], -f[mx[v]]);
}
inline void solve()
{
cin >> n;
for (int i = 1; i <= n; i++)
e[i] = {}, t[i] = f[i] = c[i] = 0;
f[1] = 1;
for (int i = 1, u, v; i < n; i++)
{
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(1, 0), dfs2(1, 0);
cout << f[n] << "\n";
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
solve();
}
:::