bzoj3091 城市旅行 LCT + 区间合并
题目传送门
https://lydsy.com/JudgeOnline/problem.php?id=3091
题解
调了整个晚自习才调出来的问题。
乍一看是个 LCT 板子题。
再看一眼还是个 LCT 板子题,不过需要考虑两个区间的结果的合并。
首先考虑到期望可以转化为每一个区间的权值和。那么对于每一个区间,我们维护一个 \(s, ls, rs, sum\) 分别表示整个区间的和,所有前缀的和,所有后缀的和,整个区间的子区间权值和。
那么在区间合并的时候,\(rs\) 会被计算右区间大小次,\(ls\) 会被计算左区间大小次,直接合并就可以了。
合并出 \(ls, rs\) 的时候考虑每一个区间的值的变化即可。
还有一个东西是加标记 \(k\) 对一个区间的影响。设区间长度为 \(len\)。
这个标记对 \(ls, rs\) 的影响很显然,就是每一个前缀的长度和 \(\cdot k\),即 $\frac{len(len+1)k}2 $。
对于 \(sum\) 的影响是所有子区间长度之和。可以从每一个长度的区间数量来求,过程中式子比较繁琐,只给出答案:\(\frac{len(len+1)(len+2)k}6\)。
注意:
- \(ls, rs, sum\) 一类东西太多,不要搞混;
- 不连通时不要操作!!!不连通时不要操作!!!不连通时不要操作!!!
时间复杂度 \(O(m\log n)\)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
const int N = 50000 + 7;
#define lc c[0]
#define rc c[1]
int n, m;
int a[N];
struct Node {
int c[2], fa, rev, sz, v, add;
ll s, sum, ls, rs;
} t[N];
int st[N];
inline bool isroot(int o) { return t[t[o].fa].lc != o && t[t[o].fa].rc != o; }
inline bool idtfy(int o) { return t[t[o].fa].rc == o; }
inline void connect(int fa, int o, int d) { t[fa].c[d] = o, t[o].fa = fa; }
inline Node add_tag(Node a, int k) {
a.v += k, a.add += k;
a.s += (ll)k * a.sz;
a.sum += (ll)a.sz * (a.sz + 1) * (a.sz + 2) / 6 * k;
a.ls += (ll)a.sz * (a.sz + 1) / 2 * k;
a.rs += (ll)a.sz * (a.sz + 1) / 2 * k;
return a;
}
inline void pushup(int o) {
assert(!t[o].rev && !t[o].add);
const Node &tl = t[t[o].lc], &tr = t[t[o].rc];
t[o].sz = tl.sz + tr.sz + 1;
t[o].s = tl.s + tr.s + t[o].v;
t[o].ls = tl.ls + (tl.s + t[o].v) * (tr.sz + 1) + tr.ls;
t[o].rs = tr.rs + (tr.s + t[o].v) * (tl.sz + 1) + tl.rs;
t[o].sum = tl.sum + tr.sum + (ll)t[o].v * (tl.sz + 1) * (tr.sz + 1) + tl.rs * (tr.sz + 1) + tr.ls * (tl.sz + 1);
}
inline void pushdown(int o) {
if (t[o].rev) {
if (t[o].lc) t[t[o].lc].rev ^= 1, std::swap(t[t[o].lc].lc, t[t[o].lc].rc), std::swap(t[t[o].lc].ls, t[t[o].lc].rs);
if (t[o].rc) t[t[o].rc].rev ^= 1, std::swap(t[t[o].rc].lc, t[t[o].rc].rc), std::swap(t[t[o].rc].ls, t[t[o].rc].rs);
t[o].rev = 0;
}
if (t[o].add) {
if (t[o].lc) t[t[o].lc] = add_tag(t[t[o].lc], t[o].add);
if (t[o].rc) t[t[o].rc] = add_tag(t[t[o].rc], t[o].add);
t[o].add = 0;
}
}
inline void rotate(int o) {
int fa = t[o].fa, pa = t[fa].fa, d1 = idtfy(o), d2 = idtfy(fa), b = t[o].c[d1 ^ 1];
if (!isroot(fa)) t[pa].c[d2] = o; t[o].fa = pa;
connect(o, fa, d1 ^ 1), connect(fa, b, d1);
pushup(fa), pushup(o);
}
inline void splay(int o) {
int x = o, tp = 0;
st[++tp] = x;
while (!isroot(x)) st[++tp] = x = t[x].fa;
while (tp) pushdown(st[tp--]);
while (!isroot(o)) {
int fa = t[o].fa;
if (isroot(fa)) rotate(o);
else if (idtfy(o) == idtfy(fa)) rotate(fa), rotate(o);
else rotate(o), rotate(o);
}
}
inline void access(int o) {
for (int x = 0; o; o = t[x = o].fa)
splay(o), t[o].rc = x, pushup(o);
}
inline void mkrt(int o) {
access(o), splay(o);
t[o].rev ^= 1, std::swap(t[o].lc, t[o].rc), std::swap(t[o].ls, t[o].rs);
}
inline int getrt(int o) {
access(o), splay(o);
while (pushdown(o), t[o].lc) o = t[o].lc;
return splay(o), o;
}
inline void link(int x, int y) {
mkrt(x);
if (getrt(y) != x) t[x].fa = y;
}
inline void cut(int x, int y) {
mkrt(x), access(y), splay(y);
if (t[y].lc == x && !t[x].rc) t[y].lc = t[x].fa = 0, pushup(y);
}
inline void work() {
while (m--) {
int opt, x, y, d;
read(opt), read(x), read(y);
if (opt == 1) cut(x, y);
else if (opt == 2) link(x, y);
else if (opt == 3) read(d), getrt(x) == getrt(y) && (mkrt(x), access(y), splay(y), t[y] = add_tag(t[y], d), 1);
else if (getrt(x) != getrt(y)) puts("-1");
else {
mkrt(x), access(y), splay(y);
ll sum = t[y].sum, cnt = (ll)t[y].sz * (t[y].sz + 1) / 2, p = std::__gcd(sum, cnt);
printf("%lld/%lld\n", sum / p, cnt / p);
}
}
}
inline void init() {
read(n), read(m);
for (int i = 1; i <= n; ++i) read(a[i]);
for (int i = 1; i <= n; ++i) t[i].v = a[i], pushup(i);
int x, y;
for (int i = 1; i < n; ++i) read(x), read(y), link(x, y);
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
bzoj3091 城市旅行 LCT + 区间合并的更多相关文章
- 【bzoj3091】城市旅行 LCT区间合并
题目描述 输入 输出 样例输入 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 样例输出 16/3 6/1 题解 LCT区间合并 前三个 ...
- BZOJ3091城市旅行——LCT区间信息合并
题目描述 输入 输出 样例输入 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 样例输出 16/3 6/1 提示 对于所有数据满足 1& ...
- BZOJ3091 城市旅行 LCT
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3091 题意概括 鉴于本人语文不好,此题的描述原题很清晰,废话不多,请看原题. 可怕,原题是图片,不 ...
- BZOJ3091: 城市旅行(LCT,数学期望)
Description Input Output Sample Input 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 1 4 1 4 Sample ...
- 【BZOJ3091】城市旅行 LCT
[BZOJ3091]城市旅行 Description Input Output Sample Input 4 5 1 3 2 5 1 2 1 3 2 4 4 2 4 1 2 4 2 3 4 3 1 4 ...
- 【LCT】BZOJ3091 城市旅行
3091: 城市旅行 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1927 Solved: 631[Submit][Status][Discuss ...
- bzoj 3091: 城市旅行 LCT
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=3091 题解: 首先前三个操作就是裸的LCT模板 只考虑第四个操作. 要求我们计算期望,所以我 ...
- BZOJ 3091: 城市旅行 [LCT splay 期望]
3091: 城市旅行 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1454 Solved: 483[Submit][Status][Discuss ...
- BZOJ 3091: 城市旅行 lct 期望 splay
https://www.lydsy.com/JudgeOnline/problem.php?id=3091 https://blog.csdn.net/popoqqq/article/details/ ...
随机推荐
- RCU原理分析
简介 RCU(Read-Copy Update)是数据同步的一种方式,在当前的Linux内核中发挥着重要的作用.RCU主要针对的数据对象是链表,目的是提高遍历读取数据的效率,为了达到目的使用RCU机制 ...
- pandas库简介和数据结构
pandas简介 pandas是一个强大的Python数据分析的工具包.是基于Numpy来构件的. pandas提供快速.灵活和富有表现力的数据结构. 主要功能: 具备对其功能的数据结构DataFra ...
- Delphi XE2 之 FireMonkey 入门(32) - 数据绑定: TBindingsList: TBindList、TBindPosition [未完成...]
Delphi XE2 之 FireMonkey 入门(32) - 数据绑定: TBindingsList: TBindList.TBindPosition [未完成...] //待补...
- cannot assign to struct field xxx in map
golang 中对 map 类型中的 struct 赋值报错 type s struct{ name string age int}func main(){ a := map[string]s{ &q ...
- [LeetCode] 272. Closest Binary Search Tree Value II 最近的二叉搜索树的值 II
Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...
- C 语言中的关键字 - 数据类型、数据修饰符及逻辑结构
C 语言中有 32 个关键字.这是留个编译器用的特殊字符串,用户不可以使用. 特殊关键字 sizeof 和 return 是 C 语言中的两个特殊关键字. sizeof sizeof 用于计算变量所占 ...
- CNN(卷积神经网络)原理讲解及简单代码
一.原理讲解 1. 卷积神经网络的应用 分类(分类预测) 检索(检索出该物体的类别) 检测(检测出图像中的物体,并标注) 分割(将图像分割出来) 人脸识别 图像生成(生成不同状态的图像) 自动驾驶 等 ...
- sql语句传参数
SET @register = '; SET @unregister = '; UPDATE cw_base_register SET register = @register, unregister ...
- 只需要2个工具,百度云盘大文件就能用迅雷和IDM下载
不会代码,不懂脚本,没关系 ,能找到一座通往它们的桥梁,照样能到达彼岸. 这里以360极速浏览器为例. 在浏览器地址框输入以下地址直接到达浏览器安装扩展插件的地方(偷个懒,复制网址吧),https:/ ...
- [Web 前端] 034 计算属性,侦听属性
目录 0. 方便起见,定个轮廓 1. 过滤器 2. 计算属性 2.1 2.2 3. 监听属性 0. 方便起见,定个轮廓 不妨记下方的程序为 code1 <!DOCTYPE html> &l ...