Description
给出一棵树。树的边权为1或-1。现在要求有多少个点对
(u,v)
满足,存在中间点
k(k≠u,v)
,
dis[u,k]=0
且
dis[k,v]=0
。
dis[u,v]
表示从
u
到
Analysis
求树上点对数的题目一般都用点分治解决。这题亦是如此,当作是点分治的练习。
这题大概要把合法点对分成三类:
- 路径经过根节点(其中,根节点作为中间点还要特殊考虑)
- 根节点为一条路径的端点
- 整个路径都在子树里面
第3点直接沿着子树递归下去即可。
第2点特判一下直接计入答案。关键是第一点。
首先把
dis[v]
(表示
v
到当前重心的dis)和
然后满足
Key Code
fo(i,1,num)
{
if(a[i].p && a[i].w==0) ans++;
lyd[N+a[i].w][a[i].p]++;
}
ll x=0;
top=a[num+1].bz=0;
if(num)
fo(i,1,num+1)
{
if(a[i].bz!=a[i-1].bz)
{
fo(k,1,top)
{
if(type[k]) x+=lyd[q[k]][0]+lyd[q[k]][1]-d[q[k]][0]-d[q[k]][1];
else x+=lyd[q[k]][1]-d[q[k]][1];
}
for(;top;top--)
d[q[top]][0]=d[q[top]][1]=d[N+N-q[top]][0]=d[N+N-q[top]][1]=0;
if(i>num) break;
}
q[++top]=N-a[i].w,type[top]=a[i].p;
d[N+a[i].w][a[i].p]++;
if(a[i].w==0) type[top]=1;
}
ans+=x/2;