专栏文章
题解:CF1527D MEX Tree
CF1527D题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minqh2y0
- 此快照首次捕获于
- 2025/12/02 06:41 3 个月前
- 此快照最后确认于
- 2025/12/02 06:41 3 个月前
某模拟赛 T1,赛后发现爆标(题解是 做法),遂来写题解。
我们发现不含 的路径 。含 的路径 ,所以可以先单独计算不含 的路径数,求出 。
对于含 的路径,我们可以从 开始枚举新添的数,并把它尝试添进答案路径中,维护答案。我们发现,添加进入答案序列并不需要 ,只需要暴力跳父亲,因为每个点最多访问一次,所以复杂度为均摊 。爆标了!!
对于含 的路径,我们可以从 开始枚举新添的数,并把它尝试添进答案路径中,维护答案。我们发现,添加进入答案序列并不需要 ,只需要暴力跳父亲,因为每个点最多访问一次,所以复杂度为均摊 。
code
CPP#include<bits/stdc++.h>
using namespace std;
#define N 200005
int n, f[N], siz[N];
long long ans[N];
bool book[N];
vector<int> mp[N];
inline dfs(int x, int y) {
f[x] = y, siz[x] = 1;
for(int i = mp[x].size() - 1; ~i; --i) {
int to = mp[x][i];
if(to ^ y) {
dfs(to, x);
if(!x) ans[0] += 1ll * (siz[to] - 1) * siz[to] >> 1;
siz[x] += siz[to];
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while(t--) {
cin >> n;
if(n == 1) {
puts("0 0");
continue;
}
for(int i = n - 1; i; --i) {
int u, v;
cin >> u >> v;
mp[u].push_back(v), mp[v].push_back(u);
}
dfs(0, 0);
int l = 1, r = 0, now = 1, as = 1;
while(f[now]) book[now] = 1, now = f[now];
book[now] = 1, book[0] = 1;
while(book[as]) ++as;
siz[0] -= siz[now];
ans[1] = 1ll * siz[0] * (siz[now] - siz[1]);
int sz = siz[0];
for(int i = mp[0].size() - 1; ~i; --i) {
int to = mp[0][i];
if(to ^ now) sz -= siz[to], ans[1] += 1ll * sz * siz[to];
}
for(int i = as; i < n; i = as) {
int ii = i;
while(!book[f[ii]]) book[ii] = 1, ii = f[ii];
book[ii] = 1;
if(f[ii] == l) {
while(book[as]) ++as;
ans[i] = 1ll * siz[r] * (siz[l] - siz[i]);
l = i;
} else if(f[ii] == r) {
while(book[as]) ++as;
ans[i] = 1ll * siz[l] * (siz[r] - siz[i]);
r = i;
} else break;
}
ans[as] = 1ll * siz[l] * siz[r];
for(int i = 0; i <= n; ++i) {
printf("%lld ", ans[i]);
ans[i] = book[i] = siz[i] = f[i] = 0;
mp[i].clear();
}
putchar('\n');
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...