不知道为什么 l g lg lg题解里清一色只会用 ∑ d = 2 m − 1 → 1 = 2 m − ∑ d \sum d=2m-1\rightarrow 1=2m-\sum d ∑d=2m−1→1=2m−∑d容斥做法
设
m
n
l
e
a
f
u
\mathit{mnleaf_u}
mnleafu表示距点
u
u
u最近的叶子节点的距离
这个可以用脚
d
f
s
dfs
dfs随便
O
(
n
/
n
l
o
g
n
)
O(n/nlogn)
O(n/nlogn)做
对于一个根的情况就是统计
∑
u
[
m
n
l
e
a
f
u
≤
d
e
p
u
&
&
m
n
l
e
a
f
f
a
[
u
]
≥
d
e
p
u
]
\sum_{u}[\mathit{mnleaf_u}\le dep_u\ \&\&\ \mathit{mnleaf_{fa[u]}}\geq dep_u]
∑u[mnleafu≤depu && mnleaffa[u]≥depu]
对于所有点询问,考虑点分治
那么一个子树中
u
u
u对另一个子树中的
v
v
v的贡献就是
[
m
n
l
e
a
f
u
≤
d
e
p
u
+
d
e
p
v
&
&
m
n
l
e
a
f
f
a
[
u
]
≥
d
e
p
u
+
d
e
p
v
]
[\mathit{mnleaf_u}\le dep_u+dep_v\ \&\&\ \mathit{mnleaf_{fa[u]}}\geq dep_u+dep_v]
[mnleafu≤depu+depv && mnleaffa[u]≥depu+depv]
移一下项就是
u
u
u区间加,
v
v
v单点求值
于是点分即可
先把整个
d
f
s
dfs
dfs然后枚举求值的子树减去这个子树自己的贡献然后随便算算即可
注意记得把当前分治中心的贡献加进去
就是往哪个子树求值就把中心的父亲设为哪个
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
return f?res:-res;
}
template<typename tp>inline void chemx(tp &a,tp b){a=max(a,b);}
template<typename tp>inline void chemn(tp &a,tp b){a=min(a,b);}
cs int N=70005;
int n,mnleaf[N],isleaf[N];
vector<int> e[N];
void dfs(int u,int fa){mnleaf[u]=1e9;int fg=0;
for(int &v:e[u])if(v!=fa){
fg=1;dfs(v,u);
chemn(mnleaf[u],mnleaf[v]+1);
}
if(!fg||(u==1&&e[u].size()==1))mnleaf[u]=0,isleaf[u]=1;
}
void dfs1(int u,int tp,int fa){
chemn(mnleaf[u],tp);
multiset<int>st;st.insert(mnleaf[u]);
for(int &v:e[u])if(v!=fa){
st.insert(mnleaf[v]+1);
}
for(int &v:e[u])if(v!=fa){
st.erase(st.find(mnleaf[v]+1));
int vl=mnleaf[v]+1;
dfs1(v,min(tp,*st.bg())+1,u);
st.insert(vl);
}
}
namespace bit{
int tr[2*N],stk[N*6],top;
#define lb(x) (x&(-x))
void write(){
for(int i=1;i<=n+n;i++)cout<<tr[i]<<" ";puts("");
}
void upd(int p,int k){stk[++top]=p;
for(;p<=n+n;p+=lb(p))tr[p]+=k;
}
void delet(int p){
for(;p<=n+n;p+=lb(p))tr[p]=0;
}
void clear(){
while(top)delet(stk[top--]);
}
void update(int l,int r,int k){
if(l>r)return;l+=n,r+=n;
upd(l,k),upd(r+1,-k);
}
int query(int p,int res=0){p+=n;
for(;p>0;p-=lb(p))res+=tr[p];return res;
}
#undef lb
};
int maxn,mxsiz,rt;
int siz[N],vis[N],fa[N],dep[N],ans[N];
void getrt(int u,int fa){
siz[u]=1;int son=0;
for(int v:e[u])if(!vis[v]&&v!=fa){
getrt(v,u),siz[u]+=siz[v];
chemx(son,siz[v]);
}chemx(son,maxn-siz[u]);
if(son<mxsiz)mxsiz=son,rt=u;
}
vector<int>nd[N];
void dfs2(int u,int root){
nd[root].pb(u),bit::update(mnleaf[u]-dep[u],mnleaf[fa[u]]-dep[u],1);
for(int v:e[u])if(!vis[v]&&v!=fa[u])fa[v]=u,dep[v]=dep[u]+1,dfs2(v,root);
}
void delet(int u){
for(int &v:nd[u])
bit::update(mnleaf[v]-dep[v],mnleaf[fa[v]]-dep[v],-1);
}
void insert(int u){
for(int &v:nd[u])
bit::update(mnleaf[v]-dep[v],mnleaf[fa[v]]-dep[v],1);
nd[u].resize(0);
}
void getans(int u){
ans[u]+=bit::query(dep[u]);
for(int v:e[u])if(!vis[v]&&v!=fa[u])getans(v);
}
void solve(int u){
vis[u]=1;
for(cs int &v:e[u])if(!vis[v]){
fa[v]=u,dep[v]=1,dfs2(v,v);
}
ans[u]+=bit::query(0);
for(cs int &v:e[u])if(!vis[v]){
delet(v);
bit::update(mnleaf[u],mnleaf[v],1);
getans(v);
bit::update(mnleaf[u],mnleaf[v],-1);
insert(v);
}
bit::clear();
for(cs int &v:e[u])if(!vis[v]){
maxn=siz[v],mxsiz=1e9,getrt(v,u);
solve(rt);
}
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read();maxn=n;mxsiz=1e9;
for(int i=1;i<n;i++){
int u=read(),v=read();
e[u].pb(v),e[v].pb(u);
}dfs(1,0);
dfs1(1,1e9,0);
getrt(1,0);
solve(rt);
for(int i=1;i<=n;i++)if(!isleaf[i])cout<<ans[i]<<'\n';else cout<<1<<'\n';
return 0;
}