题解:CF1527D MEX Tree
chenzhaoxu2027 · · 题解
致敬传奇分类讨论。
题意
给你一棵
分析
求出恰好为
如果某一个路径权值大于等于
因此我们从小到大枚举
考虑如何维护
这里给出引理:
- 如果树上某三个节点
a,b,c ,a,b 不是祖孙关系,a,b,c 两两不等且满足\{\operatorname{LCA}(a,b),c\}=\{\operatorname{LCA}(a,c),\operatorname{LCA}(b,c)\} (这两个都是可重集)那么c 就在a,b 路径上。反之亦然。
证明:
记
讨论
如果
如果
如果
如果
其他情况下假设
综上所述,等式成立的充要条件就是
这样一来我们就能够解决
然后讨论
这里比较巧妙。如果
维护好了
对于
假设“
最终复杂度:
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
int dfstime;
struct tree_heavy{
int hson,fa,sz,d;
int dfn,top;
}t[500005];
int num[500005];
vector<int> g[500005];
int ans[500005];
void dfs1(int x,int fa){
t[x].fa=fa;
t[x].sz=1;
t[x].d=t[t[x].fa].d+1;
t[x].hson=-1;
for(int i=0;i<g[x].size();i++){
int v=g[x][i];
if(v==fa){
continue;
}
dfs1(v,x);
t[x].sz+=t[v].sz;
if(t[x].hson==-1||t[t[x].hson].sz<t[v].sz){
t[x].hson=v;
}
}
}
void dfs2(int x,int tp){
t[x].top=tp;
dfstime++;
t[x].dfn=dfstime;
num[dfstime]=x;
if(t[x].hson!=-1){
dfs2(t[x].hson,tp);
}
for(int i=0;i<g[x].size();i++){
int v=g[x][i];
if(v==t[x].fa||v==t[x].hson){
continue;
}
dfs2(v,v);
}
}
int LCA(int x,int y){
while(t[x].top!=t[y].top){
if(t[t[x].top].d<t[t[y].top].d){
swap(x,y);
}
x=t[t[x].top].fa;
}
if(t[x].d<t[y].d){
swap(x,y);
}
return y;
}
int LZH(int x,int y){
while(t[x].top!=t[y].top){
if(t[t[x].top].d<t[t[y].top].d){
swap(x,y);
}
if(t[t[x].top].fa==y){
return t[x].top;
}
x=t[t[x].top].fa;
}
if(t[x].d<t[y].d){
swap(x,y);
}
return num[t[y].dfn+1];
}
int l,r;
int calc(){
int C=LCA(l,r);
if(C!=l&&C!=r){
return t[l].sz*t[r].sz;
}
if(C==l){
swap(l,r);
}
return t[l].sz*(n-t[LZH(l,r)].sz);
}
bool check(int x){
int C=LCA(l,r);
if(C!=l&&C!=r){
int cl=LCA(x,l);
int cr=LCA(x,r);
if(cl==x&&cr==C||cr==x&&cl==C){
return 1;
}
if(cl==l&&cr==C){
l=x;
return 1;
}
if(cr==r&&cl==C){
r=x;
return 1;
}
return 0;
}
if(C==l){
swap(l,r);
}
int cl=LCA(x,l);
int cr=LCA(x,r);
if(cl==l){
l=x;
return 1;
}
if(cl==x&&cr==r){
return 1;
}
if(cr==cl){
r=x;
return 1;
}
return 0;
}
void slv(){
dfstime=0;
for(int i=1;i<=n;i++){
g[i].clear();
t[i]={0,0,0,0,0,0};
}
cin>>n;
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
x++;
y++;
g[x].push_back(y);
g[y].push_back(x);
}
dfs1(1,0);
dfs2(1,1);
l=1,r=2;
ans[0]=ans[1]=n*(n-1)/2;
for(int v:g[1]){
ans[1]-=t[v].sz*(t[v].sz-1)/2;
}
ans[2]=calc();
ans[n+1]=0;
int fl=0;
for(int i=3;i<=n;i++){
if(fl||!check(i)){
fl=1;
ans[i]=0;
}
else{
ans[i]=calc();
}
}
for(int i=0;i<n;i++){
ans[i]-=ans[i+1];
}
for(int i=0;i<=n;i++){
cout<<ans[i]<<" ";
}
cout<<"\n";
}
signed main(){
int t;
cin>>t;
while(t--){
slv();
}
return 0;
}
附图: