题解:HDU 7435
1. Description
给定一棵根为 \(1\) 的有根树,点 \(x\) 的点权为 \(A_x\),定义 \(S(u)\) 表示以 \(u\) 为根的子树对应的点集,\(g_{u,v}= \max(A_u,A_v)\times|A_u-A_v|\),\(f_i=\sum_{u\in S(i)}\sum_{v\in S(i)} g_{u,v}\),对于 \(1\le i\le n\),求出 \(f_i\)。
2. Solution
首先一个很简单的分解 \(f_i=\sum_{u\in son_i} f_u+\sum_{u\in son_i}\sum_{v\in son_i}val(u,v)\),其中 \(val(u,v)\) 表示 \(\sum_{x\in S(u)}\sum_{y\in S(v)} g_{x,y}\),特殊的,\(val(u,u)=0\)。
我们现在考虑怎么求出所有的 \(val(u,v)\),显然可以使用树上启发式合并求解,将重儿子对应的子树点集作为初始集合,依次枚举轻儿子,在 \(f_i\) 中加上轻儿子对应的子树点集与当前集合的贡献,然后将轻儿子对应的子树点集加入集合即可。
然后简单的推式子,将 \(g_{u,v}\) 的式子略微分类讨论一下有 \(g_{u,v}=\begin{cases}A_u^2-A_u\times A_v\ (A_u\ge A_v)\\A_v^2-A_u\times A_v\ (A_u<A_v)\end{cases}\),只需要使用权值树状数组分别维护当前集合的零次方和,一次方和,二次方和,就可以在 \(O(\log n)\) 的时间复杂度内求解出一个点对于一个点集的贡献。
最后时间复杂度为 \(O(n\log^2 n)\),足够通过此题了。
3. Code
/*by qwer6*/
/*略去缺省源和快读快写*/
const int N=5e5+5;
int n,cnt_dfn,tot;
ull ans;
int siz[N],son[N],dfn[N],L[N],R[N];
ull a[N],tmp[N],f[N];
struct Chain_forward_star{
struct Edge{
int v,nxt;
}e[N<<1];
int cnt_edge;
int head[N];
void AddEdge(int u,int v){
e[++cnt_edge]={v,head[u]};
head[u]=cnt_edge;
}
}G;
struct Node{
ull sum0,sum1,sum2;
Node(ull _sum0=0,ull _sum1=0,ull _sum2=0){
sum0=_sum0,sum1=_sum1,sum2=_sum2;
}
Node operator +(const Node &a)const{
return {sum0+a.sum0,sum1+a.sum1,sum2+a.sum2};
}
Node operator -(const Node &a)const{
return {sum0-a.sum0,sum1-a.sum1,sum2-a.sum2};
}
void print(){
write(sum0),Spa,write(sum1),Spa,write(sum2),Nxt;
}
};
struct Binary_tree{
Node c[N];
#define lowbit(x) (x&-x)
void add(int x,Node v){
for(int i=x;i<=tot;i+=lowbit(i))c[i]=c[i]+v;
}
void sub(int x,Node v){
for(int i=x;i<=tot;i+=lowbit(i))c[i]=c[i]-v;
}
Node query(int x){
Node res;
for(int i=x;i;i-=lowbit(i))res=res+c[i];
return res;
}
Node query(int l,int r){
return query(r)-query(l-1);
}
#undef lowbit
}bit;
ull count(int x){
ull res=0;
if(x<tot){
Node Ans=bit.query(x+1,tot);
res+=Ans.sum2-tmp[x]*Ans.sum1;
}
if(x>1){
Node Ans=bit.query(1,x-1);
res+=Ans.sum0*tmp[x]*tmp[x]-tmp[x]*Ans.sum1;
}
return res;
}
void dfs(int u,int fa){
siz[u]=1;
L[u]=++cnt_dfn;
dfn[cnt_dfn]=u;
a[u]=lower_bound(tmp+1,tmp+tot+1,a[u])-tmp;
for(int i=G.head[u],v;i;i=G.e[i].nxt){
v=G.e[i].v;
if(v==fa)continue;
dfs(v,u);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v])son[u]=v;
}
R[u]=cnt_dfn;
}
void redfs(int u,int fa,bool flag){
for(int i=G.head[u],v;i;i=G.e[i].nxt){
v=G.e[i].v;
if(v==fa||v==son[u])continue;
redfs(v,u,1);
f[u]+=f[v];
}
if(son[u])redfs(son[u],u,0),f[u]+=f[son[u]];
for(int i=G.head[u],v;i;i=G.e[i].nxt){
v=G.e[i].v;
if(v==fa||v==son[u])continue;
for(int j=L[v];j<=R[v];j++)
f[u]+=count(a[dfn[j]]);
for(int j=L[v],x;j<=R[v];j++){
x=a[dfn[j]];
bit.add(x,Node(1,tmp[x],tmp[x]*tmp[x]));
}
}
f[u]+=count(a[u]);
bit.add(a[u],Node(1,tmp[a[u]],tmp[a[u]]*tmp[a[u]]));
if(flag){
for(int i=L[u],x;i<=R[u];i++){
x=a[dfn[i]];
bit.sub(x,Node(1,tmp[x],tmp[x]*tmp[x]));
}
}
ans^=(f[u]*2);
}
signed main(){
read(n);
for(int i=2,u,v;i<=n;i++){
read(u),read(v);
G.AddEdge(u,v);
G.AddEdge(v,u);
}
for(int i=1;i<=n;i++)tmp[i]=read(a[i]);
sort(tmp+1,tmp+n+1);
tot=unique(tmp+1,tmp+n+1)-tmp-1;
dfs(1,0);
redfs(1,0,0);
write(ans);
}

浙公网安备 33010602011771号