题解:CF2222G Statistics on Tree
直接考虑点分治类似,容易转化为统计
硬做会带若干个老哥。发现
但是点分治其实也会多带老哥。考虑以重心为根,
考虑第一部分,即
考虑第二部分,容易转化为
:::success[点击查看参考代码]
#include<bits/stdc++.h>
#define TIME chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count()
#define rep(i,l,r) for(int qwp=(r),i=(l);i<=qwp;i++)
#define per(i,r,l) for(int qwp=(l),i=(r);i>=qwp;i--)
#define pb push_back
#define clr clear
#define SZ(x) (int)((x).size())
#define LB lower_bound
#define fir first
#define sec second
using namespace std;
namespace c0dE1ng{
typedef long long ll;
typedef vector<int> arr;
constexpr int N=1e5+5;
int n;arr g[N];ll ans[N];
int sz[N],rt,rtv;void dfs1(const int u,const int pre){
sz[u]=1;int t=0;for(auto v:g[u])if(v!=pre)
dfs1(v,u),sz[u]+=sz[v],t=max(t,sz[v]);
t=max(t,n-sz[u]);if(t<rtv)rt=u,rtv=t;
}
arr a[N];void dfs2(const int u,const int pre,const int to,int mx){
for(auto v:g[u])if(v!=pre)dfs2(v,u,to,max(mx,sz[u]-sz[v]));
mx=max(mx,sz[u]),a[to].pb(mx);
}
map<int,int>cnt;void dfs3(const int u,const int pre){
arr a;for(auto v:g[u])if(v!=pre)dfs3(v,u),a.pb(sz[v]);
cnt.clr();for(auto t:a){
for(auto w:cnt)ans[n-w.fir-t]+=w.sec*1ll*t;
if(pre)ans[n-t]+=t;cnt[t]+=t;
}
}
int cc[N];
void slv(){
cin>>n;rep(i,1,n)g[i].clr();rep(i,1,n-1){int x,y;cin>>x>>y;g[x].pb(y),g[y].pb(x);}
rtv=n+1,dfs1(1,0),dfs1(rt,0);
rep(i,1,n-1)ans[i]=0;ans[n]=n;
for(auto v:g[rt]){
a[v].clr(),dfs2(v,rt,v,0);
for(auto t:a[v])ans[max(t,n-sz[v])]++;
}
dfs3(rt,0);for(auto v:g[rt])sort(a[v].begin(),a[v].end());
rep(i,0,SZ(g[rt])-1){
const int x=g[rt][i];if(sz[x]<n/3)continue;
rep(_,0,SZ(a[x]))cc[_]=0;
rep(j,0,SZ(g[rt])-1){
const int y=g[rt][j];if(y<=x&&sz[y]>=n/3)continue;
const int t=n-sz[x]-sz[y];ans[t]-=sz[x]*1ll*sz[y]-(LB(a[x].begin(),a[x].end(),t)-a[x].begin())*1ll*(LB(a[y].begin(),a[y].end(),t)-a[y].begin());
for(auto q:a[y]){
cc[LB(a[x].begin(),a[x].end(),max(q,t))-a[x].begin()]++;
if(q>=t)ans[q]+=LB(a[x].begin(),a[x].end(),q)-a[x].begin();
}
}
for(int _=0,sum=0;sum+=cc[_],_<SZ(a[x]);_++)ans[a[x][_]]+=sum;
}
rep(i,1,n)cout<<ans[i]<<' ';cout<<'\n';
}
void main(){
cin.tie(0)->sync_with_stdio(0);
int T;cin>>T;
while(T--)slv();
}
}
int main(){
auto _Tbe=TIME;
c0dE1ng::main();
auto _Ted=TIME;
cerr<<"\nTIME:"<<_Ted-_Tbe<<"ms\n";
return 0;
}
/*
ulimit -s 1048576
g++ -O2 -std=c++14 -static A.cpp -o %;size %;./% < A.in > A.out
*/
:::