简要题意

\(m\) 个操作,每次操作都会产生一个树的版本 \((\)从 \(0\) 开始\()\).

一次操作把 \(x_i\) 版本的树的点 \(u\) 和 \(y_i\) 版本的树的点 \(v\) 连一条权值是 \(w\) 的边。\((\) \(y_i\) 上的全部点的编号加 \(siz_{x_i}\) \()\)

求每个版本:

\[\sum_{i = 1}^{siz - 1} \sum_{j = i + 1}^{siz} dis(i, j)
\]

\(m\le 300,u,v\leq 10^{18}, siz \leq 2 \times 10 ^{18}\)

解题思路

首先,将答案考虑为每条边乘上两边的子树大小。

然后,考虑产生的新版本 (记为 \(z\) ) 的答案 \(ans_z\) 的组成:

  • 原来版本内的路径和:\(ans_x+ans_y\);
  • 边 \((u,v,w)\) 的贡献:\(siz_x\times siz_y\times w\);
  • 版本间的贡献 ( 记 \(f_x(u)\) 为版本 \(x\) 中,所有点到 \(u\) 的路径和):\(f_x(u)\times siz_y+f_y(v)\times siz_x\).

那么现在的主要问题就是每次如何得到 \(f_x(u)\)。( 记 \(dis_x(u,v)\) 表示版本 \(x\) 中,\(u\) 到 \(v\) 的路径长度)

还是分析当得到一个新的版本 \(z\) 时,\(f_z(a)\) 的组成:

  • 若 \(a\) 原来属于版本 \(x\),\(f_x(a)+f_y(v)+(w+dis_x(a, u))\times siz_y\).
  • 若 \(a\) 原来属于版本 \(y\),\(f_y(a)+f_x(u)+(w+dis_y(a, v))\times siz_x\).

此时,\(f_x(u)/f_y(v)\) 算作已知,故只需考虑 \(dis_z(a,b)\) 如何计算:

  • \(a,b\) 都在版本 \(x/y\),调用 \(dis_{x/y}(a,b)\);
  • \(a,b\) 不在同一版本,\(dis_x(a,u)+w+dis_y(b_v)\).

此时整个问题在递归中解决了,现在来分析一下复杂度。

对于 \(f_x(u)\),版本数是 \(O(m)\) 级别,\(u\) 的取值是 \(O(m)\) 级别,总的状态就是 \(O(m^2)\) 级别,转移 \(O(1)\)。

\(dis_x(a, b)\) 的计算平均是 \(O(1)\) 的,所以计算所有的 \(f_x(u)\) 是 \(O(m^2)\) 的。

计算 \(ans\) 时, \(f_x(u)\) 会被调用 \(O(m)\) 次,所以总的时间复杂度是 \(O(m^3)\)。

代码

inline int Dis(int z, int a, int b){
if(a == b) return 0;
if(dis[z].find({a, b}) != dis[z].end()) return dis[z][{a, b}];
int x = X[z], y = Y[z], w = W[z]; LL u = U[z], v = V[z];
if(a <= siz[x] && b <= siz[x]) return dis[z][{a, b}] = Dis(x, a, b);
if(siz[x] < a && siz[x] < b) return dis[z][{a, b}] = Dis(y, a - siz[x], b - siz[x]);
int sum = w; if(a > siz[x]) swap(a, b);
Plus(sum, Dis(x, a, u)), Plus(sum, Dis(y, b - siz[x], v));
return dis[z][{a, b}] = sum;
}
inline int F(int z, LL a){
if(z == 0 && a == 1) return 0;
if(f[z].find(a) != f[z].end()) return f[z][a];
int x = X[z], y = Y[z], w = W[z]; LL u = U[z], v = V[z];
if(a <= siz[x]){
int sum = 0;
Plus(sum, F(x, a)), Plus(sum, F(y, v));
Plus(sum, siz[y] % mod * Mod(w + Dis(x, a, u) - mod) % mod);
return f[z][a] = sum;
}
int sum = 0;
Plus(sum, F(y, a - siz[x])), Plus(sum, F(x, u));
Plus(sum, siz[x] % mod * Mod(w + Dis(y, a - siz[x], v) - mod) % mod);
return f[z][a] = sum;
}
inline void solve(int x, int y, LL u, LL v, int w, int z){
X[z] = x, Y[z] = y, U[z] = u, V[z] = v, W[z] = w;
Plus(Ans[z], Mod(Ans[x] + Ans[y] - mod));
Plus(Ans[z], siz[x] % mod * (siz[y] % mod) % mod * w % mod);
Plus(Ans[z], Mod(siz[y] % mod * F(x, u) % mod + siz[x] % mod * F(y, v) % mod - mod));
siz[z] = siz[x] + siz[y];
}

参考

https://www.cnblogs.com/qjbqjb/p/15905279.html

[题解][YZOJ50113] 枇杷树的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. ZooKeeper 面试题?

    ZooKeeper 是一个开放源码的分布式协调服务,它是集群的管理者,监视着集群 中各个节点的状态根据节点提交的反馈进行下一步合理操作.最终,将简单易用 的接口和性能高效.功能稳定的系统提供给用户. ...

  2. phpstorm+xdebug调试详细教程

    对于PHP开发,初来咋到,开发环境的搭建和理解感觉是最烦人的一件事了.不像JAVA,打开一个Eclipse就可以开搞,Php的Debug都要几个插件来配合工作.这些都是死的,好说.但是对于Xdebug ...

  3. 什么是JDK?什么是JRE?说说它们之间的区别?

     JDK (Java Development Kit)  JDK是整个Java的核心,包括了Java运行环境JRE(Java Runtime Envirnment),一堆Java工具(javac,ja ...

  4. Javascript 占位符替换

    String.prototype.format=function(){ if(arguments.length===0){ return String(this); } let reg=/(\{\d\ ...

  5. 学习openstack(三)

      一.OpenStack初探 1.1 OpenStack简介 OpenStack是一整套开源软件项目的综合,它允许企业或服务提供者建立.运行自己的云计算和存储设施.Rackspace与NASA是最初 ...

  6. torch.optim.SGD参数详解

    随机梯度下降法 $\theta_{t} \leftarrow \theta_{t-1}-\alpha g_{t}$ Code: optimzer = torch.optim.SGD(model.par ...

  7. ES6-11学习笔记--代理Proxy

    Proxy代理 常用拦截方法 ES5拦截: let obj = {} let newVal = '' Object.defineProperty(obj, 'name', { get() { cons ...

  8. Python窗口学习之给按钮美化

    tkinter的按钮很丑也很难改 怎么办呢? 最好的方法就是不用按钮! 给Label添加点击事件,和按钮的作用是一样的! 代码: #!/usr/bin/env python # -*- coding: ...

  9. C语言---魔方阵

    魔方阵的定义:在n*n的方阵中,每一行的和=每一列的和=对角线的和.(本文中涉及的n为大于3的奇数). 例如3*3的魔方阵为: 5*5的魔方阵为: 如何写魔方阵呢? 1.数字1位于第一行的正中间2.下 ...

  10. 什么是机器学习的分类算法?【K-近邻算法(KNN)、交叉验证、朴素贝叶斯算法、决策树、随机森林】

    1.K-近邻算法(KNN) 1.1 定义 (KNN,K-NearestNeighbor) 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类 ...