给定一棵 n n n 个节点,以 1 1 1 为根的有根树,每个点有一个权值 w i w_i wi。你可以把所有点
分进两个集合 A A A 和 B B B 中,定义一种划分方案的代价为:
∑ x ∈ A ∑ y ∈ A ( ( F ( x , y ) ∧ w x > w y ) ∨ G ( x , y ) ) + ∑ x ∈ A d x + ∑ x ∈ B ∑ y ∈ B ( F ( x , y ) ∧ w x < w y ) \sum_{x \in A} \sum_{y \in A} ((F(x, y) \land w_x > w_y) \lor G(x, y)) + \sum_{x \in A} d_x + \sum_{x \in B} \sum_{y \in B} (F(x, y) \land w_x < w_y) x∈A∑y∈A∑((F(x,y)∧wx>wy)∨G(x,y))+x∈A∑dx+x∈B∑y∈B∑(F(x,y)∧wx<wy)
其中 d x d_x dx 表示 x x x 的深度 (到根的距离), F ( x , y ) F(x, y) F(x,y) 表示 x x x 是否是 y y y 的祖先,是则为 1 1 1,否则为 0 0 0, G ( x , y ) G(x, y) G(x,y) 表示是否满足 x < y x < y x<y 且 x , y x, y x,y 没有祖先关系,是则为 1 1 1,否则为 0 0 0。
请你对于每个 0 ≤ i ≤ n 0 \le i \le n 0≤i≤n 求出满足 ∣ B ∣ = i \lvert B \rvert = i ∣B∣=i 的前提下代价最小划分方案的代价,并输出。
第一行包含一个整数 n n n,表示点数。
接下来一行 N N N 个整数 w i w_i wi,表示每个点的权值。
接下来 N − 1 N − 1 N−1 行,每行两个整数 u , v u, v u,v,表示一条 u u u 到 v v v 的边。
输出 n + 1 n + 1 n+1 行每行一个整数,第 i i i 行表示 ∣ B ∣ = i − 1 \lvert B \rvert = i − 1 ∣B∣=i−1 时的答案。
样例输入
4
4 1 2 3
1 2
2 3
2 4
样例输出
9
5
2
1
2
对于所有数据,保证 1 ≤ n , w i ≤ 5 × 1 0 5 , 1 ≤ u , v ≤ n 1 \leq n, w_i \leq 5 \times 10^5, 1 \leq u, v \leq n 1≤n,wi≤5×105,1≤u,v≤n。
subtask 1 (10pts): N ≤ 20 N \leq 20 N≤20;
subtask 2 (20pts): N ≤ 500 N \leq 500 N≤500;
subtask 3 (35pts): w i w_i wi 互不相同;
subtask 4 (35pts): 没有其它限制。
题解:
首先,我们把柿子化成:
∣ A ∣ × ( ∣ A ∣ − 1 ) − ∑ x ∈ A ∑ y ∈ A ( F ( x , y ) ∧ w x ≤ w y ) + ∑ x ∈ A d x + ∑ x ∈ B ∑ y ∈ B ( F ( x , y ) ∧ w x < w y ) |A|\times(|A|-1)-\sum_{x \in A} \sum_{y \in A} (F(x, y) \land w_x \leq w_y)+ \sum_{x \in A} d_x + \sum_{x \in B} \sum_{y \in B} (F(x, y) \land w_x < w_y) ∣A∣×(∣A∣−1)−∑x∈A∑y∈A(F(x,y)∧wx≤wy)+∑x∈Adx+∑x∈B∑y∈B(F(x,y)∧wx<wy)
然后发现有个长得很像的柿子。这时思考为什么符号不一样。加号和减号,十分类似进集合和出集合。
那么思路就来了。
考虑先求出 ∣ B ∣ = n |B|=n ∣B∣=n。(因为 B B B 的柿子短)
那答案就 dfs 时用树状数组维护。
假设所有点权值不同。
考虑差值:设 x x x 从 B B B 到 A A A。
那么 △ = \triangle = △= d x + d_x+ dx+ ( i , x ) (i,x) (i,x)为祖先关系且祖先小于儿子的对数。这是一个常数。直接从大往小取。
当存在点权值相同时。
因为差距只在存在祖孙关系的点,那么微扰相邻。发现若父亲比儿子先进 A A A,设 a x a_x ax 表示 x x x 祖先中比它小的个数, b x b_x bx 表示子孙中大于 x x x 的个数。那么对于父亲 u u u 和 子孙 v v v, a v − a u ≤ d v − d u a_v-a_u\leq d_v-d_u av−au≤dv−du, b v ≤ b u b_v\leq b_u bv≤bu,而且深度越小子孙越多,对 A A A 的贡献越大。所以一定先加祖先。
那么设 c x c_x cx 表示祖先中权值等于 x x x 的个数。按照 d x − a x − b x − c x d_x-a_x-b_x-c_x dx−ax−bx−cx 贪心取就可以了。
#include<bits/stdc++.h>
#define N 500005
typedef long long ll;
using namespace std;
int read(){
int op=1,sum=0;char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
return op*sum;
}
ll w[N],dep[N],a[N],b[N],c[N];
int dfn[N],dfs_num,n,sz[N],q[N];
vector<int> to[N];
const int inf=5e5;
struct BIT{
ll t[N];
inline void init(){
memset(t,0,sizeof(t));
}
inline ll get(int x){
ll now=0;
for(;x;x-=(x&-x))now+=t[x];
return now;
}
inline void add(int x,ll val){
for(;x<=inf;x+=(x&-x))t[x]+=val;
}
}T[3];
void dfs(int x,int las){
dfn[x]=++dfs_num;
q[dfs_num]=x;
a[x]+=T[0].get(w[x]-1);
c[x]+=T[0].get(w[x])-a[x];
sz[x]=1;
T[0].add(w[x],1);
for(int i=0;i<to[x].size();++i){
int y=to[x][i];
if(y==las)continue;
dep[y]=dep[x]+1;
dfs(y,x);
sz[x]+=sz[y];
}
T[0].add(w[x],-1);
}
struct node{
int l,x,op,id;
}qu[N<<1];
bool cmp(node a,node b){
return a.l<b.l;}
int qt;
ll ans[N];
priority_queue<ll> Q;
int main(){
n=read();
for(int i=1;i<=n;++i)w[i]=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
to[x].push_back(y);to[y].push_back(x);
}
T[0].init();
dep[1]=1;
dfs(1,0);
for(int i=1;i<=n;++i){
qu[++qt].l=dfn[i],qu[qt].x=w[i],qu[qt].op=-1,qu[qt].id=i;
qu[++qt].l=dfn[i]+sz[i]-1,qu[qt].x=w[i],qu[qt].op=1,qu[qt].id=i;
}
sort(qu+1,qu+1+qt,cmp);
T[0].init();
for(int i=1,j=1;i<=n;++i){
T[0].add(w[q[i]],1);
while(j<=qt&&qu[j].l<=i){
b[qu[j].id]+=qu[j].op*(T[0].get(inf)-T[0].get(qu[j].x));
++j;
}
}
for(int i=1;i<=n;++i)ans[n]+=a[i];
for(int i=1;i<=n;++i){
Q.push(-(dep[i]-1-a[i]-b[i]-c[i]));
}
for(int i=n-1;i+1;--i){
ll now=-Q.top();
ans[i]=ans[i+1]+now;
Q.pop();
}
for(int i=0;i<=n;++i){
ans[i]+=1ll*(n-i)*(n-i-1)/2;
printf("%lld\n",ans[i]);
}
return 0;
}