本文同步发布于我的网站

Problem

给一棵根为 1 的有根树,点 \(i\) 具有一个权值 \(A_i\) 。

定义一个点对的值 \(f(u, v)=\max \left(A_u, A_v\right) \times\left|A_u-A_v\right|\) 。

你需要对于每个节点 \(i\) ,计算 \(a n s_i=\sum_{u \in \operatorname{subtree}(i), v \in \operatorname{subtree}(i)} f(u, v)\) ,其中 \(\operatorname{subtree}(i)\) 表示 \(i\) 的子树。

请你输出 \(\oplus\left(a n s_i \bmod 2^{64}\right)\) ,其中 \(\oplus\) 表示 XOR。

\(n \leq 5 \times 10^5, 1 \leq A_i \leq 10^6\)

Solution

先来愉快的推式子。

其实 \(\max \left(A_u, A_v\right) \times\left|A_u-A_v\right|\) 其实就是 \(\max^2-\max \cdot \min\),这两部分可以分开思考。

对于 \(\max\cdot\min\),其实就是在 \(i\) 的子树内任选两个点 \(u,v\in \operatorname{subtree}(i)\) 相乘

\[\begin{align}
&\sum_{u} \sum_{v } A_u\times A_v\\
=&\sum_{u }A_u\sum_{v}A_v\\
=&(\sum_{u}A_u)^2
\end{align}
\]

对于 \(\max ^2\),也就是 \(\sum_{u,v\in \operatorname{subtree}(i)}(\max(A_u,A_v))^2\),我们需要思考子树合并的情况。

假设我们已经计算了节点 \(u\) 的所有子节点的子树的内部信息,\(v\) 是 \(u\) 的某个儿子,此时我们需要计算

  • \(u\) 与 \(\operatorname{subtree}(v)\) 之间的贡献
  • \(\operatorname{subtree}(v_i)\) 与 \(\operatorname{subtree}(v_j)\) 之间的贡献(即跨点 \(u\) 的两点之间的贡献)

我们按照以下方式合并的同时计算贡献(以下步骤来自于题解)

  • \(\operatorname{subtree}(u)\) 初始为 \(\{u\}\) 。
  • 计算 \(\operatorname{subtree}(v)\) 和当前 \(\operatorname{subtree}(u)\) 之间点对的答案。(跨越 \(u\) 节点的部分)。
  • 把 \(\operatorname{subtree}(v)\) 子树内的答案直接累加。(不跨越 \(u\) 节点的部分)。
  • \(\operatorname{subtree}(u) \leftarrow \operatorname{subtree}(u)+\operatorname{subtree}(v)\) (将 \(v\) 的子树加入到 \(u\) 中)。

我们需要维护两个变量:一个子树内的权值出现次数 \(cnt\) 与权值平方和 \(sum\)。

当前子树 \(\operatorname{subtree}(u)\) 内加入一个权重为 \(w\) 的点,对于答案贡献多少呢?

  • 对于 \(\operatorname{subtree}(u)\) 中每个权值小于 \(w\) 的点,贡献 \(1\times w^2\),总计 \(2\times\sum_{i=1}^{w-1} cnt_i\times w^2\)。

  • 对于 \(\operatorname{subtree}(u)\) 中每个权值大于等于 \(w\) 的点(权重为 \(w^\prime\)),贡献 \(1\times {w^\prime}^2\),总计 \(2\times\sum_{i=w}^{10^6}sum_i\)

对于每个节点,我们开一颗线段树。初始时,每个节点的线段树只包含其本身点权。计算完某个点所有儿子的 \(ans\) 之后,我们将所有儿子的线段树合并到其自己上,同时计算贡献。

Code

#define N 500010
#define M 1000000
ULL a[N];
int n; namespace Tree
{
int head[N],nxt[N*2],ver[N*2],f[N];
int cnt;
void insert(int x,int y)
{
nxt[++cnt]=head[x];
head[x]=cnt;
ver[cnt]=y;
} }; using Tree::insert;
using Tree::head;
using Tree::nxt;
using Tree::ver; namespace Seg
{
struct Node
{
int ls,rs,l,r;
ULL sum,cnt;
#define ls(x) a[x].ls
#define rs(x) a[x].rs
#define l(x) a[x].l
#define r(x) a[x].r
#define sum(x) a[x].sum
#define cnt(x) a[x].cnt
}a[N*40];
int cnt;
int root[N];
int new_node(int l,int r)
{
cnt++;
l(cnt)=l;
r(cnt)=r;
return cnt;
} void add(int &p,int x)
{
debug
if(p==0) p=new_node(1,M);
if(l(p)==r(p))
{
debug
sum(p)+=(ULL)(x)*x;
cnt(p)++;
return;
}
int mid=(l(p)+r(p))/2;
if(x<=mid)
{
if(!ls(p)) ls(p)=new_node(l(p),mid);
add(ls(p),x);
}
else
{
if(!rs(p)) rs(p)=new_node(mid+1,r(p));
add(rs(p),x);
}
cnt(p)=cnt(ls(p))+cnt(rs(p));
sum(p)=sum(ls(p))+sum(rs(p));
} int merge(int x,int y,ULL &ans)
{
if(!x) return y;
if(!y) return x;
if(l(x)==r(x))
{
ans+=2*cnt(x)*sum(y);
sum(x)+=sum(y);
cnt(x)+=cnt(y);
return x;
} sum(x)+=sum(y);
cnt(x)+=cnt(y); ans+=2*cnt(ls(x))*sum(rs(y));
ans+=2*cnt(ls(y))*sum(rs(x)); ls(x)=merge(ls(x),ls(y),ans);
rs(x)=merge(rs(x),rs(y),ans); return x;
} }; using Seg::add;
using Seg::merge;
using Seg::root; ULL sq[N],ans[N],sum[N]; void dfs(int x,int f)
{
sum[x]=a[x];
sq[x]=a[x]*a[x];
add(root[x],a[x]);
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];
if(y==f) continue;
dfs(y,x);
sum[x]+=sum[y];
sq[x]+=sq[y];
root[x]=merge(root[x],root[y],sq[x]);
}
ans[x]=sq[x]-sum[x]*sum[x];
} int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout.precision(10);
int t=1;
// cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
Tree::insert(x,y);
Tree::insert(y,x);
}
for(int i=1;i<=n;i++)
{
cin>>a[i];
} dfs(1,0); ULL out=0;
for(int i=1;i<=n;i++)
{
out^=ans[i];
// cout<<ans[i]<<" ";
}
cout<<out<<endl; }
return 0;
}

2024杭电钉耙1-1003 HDOJ7435 树的更多相关文章

  1. 杭电 HDU ACM 2795 Billboard(线段树伪装版)

    Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  2. 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)

    以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...

  3. 杭电ACM题单

    杭电acm题目分类版本1 1002 简单的大数 1003 DP经典问题,最大连续子段和 1004 简单题 1005 找规律(循环点) 1006 感觉有点BT的题,我到现在还没过 1007 经典问题,最 ...

  4. 杭电ACM分类

    杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze ...

  5. 杭电acm习题分类

    专注于C语言编程 C Programming Practice Problems (Programming Challenges) 杭电ACM题目分类 基础题:1000.1001.1004.1005. ...

  6. 杭电 1272 POJ 1308 小希的迷宫

    这道题是我学了并查集过后做的第三个题,教我们的学姐说这是并查集的基础题,所以有必要牢牢掌握. 下面就我做这道题的经验,给大家一些建议吧!当然,我的建议不是最好的,还请各位大神指出我的错误来,我也好改正 ...

  7. 杭电acm阶段之理工大版

    想參加全国软件设计大赛C/C++语言组的同学,假设前一篇<C和指针课后练习题总结>没看完的,请先看完而且依照上面的训练做完,然后做以下的训练. 传送门:http://blog.csdn.n ...

  8. 2018 Multi-University Training Contest 1 杭电多校第一场

    抱着可能杭电的多校1比牛客的多校1更恐怖的想法 看到三道签到题 幸福的都快哭出来了好吗 1001  Maximum Multiple(hdoj 6298) 链接:http://acm.hdu.edu. ...

  9. 2017杭电ACM集训队单人排位赛 - 6

    2017杭电ACM集训队单人排位赛 - 6 排名 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 59 1 X X 1 1 X X 0 1 ...

  10. acm入门 杭电1001题 有关溢出的考虑

    最近在尝试做acm试题,刚刚是1001题就把我困住了,这是题目: Problem Description In this problem, your task is to calculate SUM( ...

随机推荐

  1. Golang 入门 : Go语言介绍

    简介 Go 语言又称 Golang,由 Google 公司于 2009 年发布,近几年伴随着云计算.微服务.分布式的发展而迅速崛起,跻身主流编程语言之列,和 Java 类似,它是一门静态的.强类型的. ...

  2. Nginx 之fastcgi常用配置项说明

    在LNMP环境中,我们都知道nginx如果要解析php脚本语言,就必须通过配置fastcgi模块来提供对php支持,那么在配置fastcgi的时候,关于fastcgi配置项的值应该怎么设置才能让其发挥 ...

  3. SQLSTATE[HY000] [2002] Connection refused报错 PHP连接docker容器中的mysql

    Laradock 是基于 Docker 提供的完整 PHP 本地开发环境 在框架中连接 MySQL 时 报错 SQLSTATE[HY000] [2002] Connection refused 主要还 ...

  4. Docker Hub 镜像加速器——持续更新(2025年3月12日)

    国内从 Docker Hub 拉取镜像有时会遇到困难,此时可以配置镜像加速器.Docker 官方和国内很多云服务商都提供了国内加速器服务. 配置加速地址 Ubuntu 16.04+.Debian 8+ ...

  5. 如何学习 ROS+PX4

    博客地址:https://www.cnblogs.com/zylyehuo/ 参考 https://www.bilibili.com/video/BV1vx4y1Y7Tu?spm_id_from=33 ...

  6. 接口常用code码

    // Informational 1xx 100 => 'Continue', 101 => 'Switching Protocols', // Success 2xx 200 => ...

  7. TCP协议详细介绍

    TCP报文格式: 字段介绍: 源/目的端口:用来标识主机上的程序 序号(seq):4个byte,指当前tcp报文段中第一个字节的序号(tcp报文中每个字节都有一个编号) 确认号(ack):4个byte ...

  8. 在Java集合框架中,`Set`接口是一个重要的接口,它表示一个不包含重复元素的集合。常见的`Set`实现类有`HashSet`、`LinkedHashSet`和`TreeSet`。下面是关于`Set`接口的一些基本用法和方法介绍:

    常用实现类 HashSet: 基于哈希表实现,元素无序. 插入.删除.查找操作的时间复杂度为O(1). LinkedHashSet: 继承自HashSet,并使用双向链表来维护元素的插入顺序. 保留元 ...

  9. golang实现命令行程序的使用帮助

    通过flag包我们可以很方便的实现命令行程序的参数标志, 接下来我们来看看如何实现命令行程序的使用帮助, 通常以参数标志-h或--help的形式来使用. 自动生成使用帮助 我们只需要声明其他参数标志, ...

  10. k8s部署dify详细过程

    一.概述 dify官方提供的安装方式是docker-compose方式部署的,单机运行. 但是在企业生产环境,单机没法提供冗余,一旦故障,就很麻烦了. 如果有大量的APP用户,那么单机承受不住这么多并 ...