F题dfs序题解
考虑从1为根的子树开始累加贡献,不难发现,一颗子树的贡献为从1开始的连续段的长度,而在dfs序上,以k为根,子树大小为siz[k]的子树恰好为[dfn[k],dfn[k]+siz[k]-1]的一段连续区间,所以设初始贡献为sum=1,当sum+1出现在子树中时,sum++,这样以k为根的子树贡献便统计完了,将k迭代为k的父节点,直至遍历到树根n
``` #include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define ios ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-6;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
int h[N], e[N<<1], ne[N<<1], idx = 1;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int fa[N], siz[N], cnt = 0, dfn[N];
void dfs(int u, int f)
{
fa[u] = f;
siz[u] = 1;
dfn[u] = ++cnt;
for (int i = h[u];i != 0;i = ne[i])
{
int j = e[i];
if (j == f)continue;
dfs(j, u);
siz[u] += siz[j];
}
}
void solve()
{
int n;
cin >> n;
for (int i = 1;i < n;i++)
{
int u, v;
cin >> u >> v;
add(u, v), add(v, u);
}
dfs(n, 0);
int ans = 0, sum = 1;
int root = 1;
while (sum < n)
{
while (sum < n && dfn[sum + 1] >= dfn[root] && dfn[sum + 1] <= dfn[root] + siz[root] - 1)
{
sum++;
}
if (sum == n)break;
ans += sum;
root = fa[root];
}
cout << ans + n << endl;
}
signed main()
{
int t;
t = 1;
while (t--)
{
solve();
}
return 0;
}