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/ ...
随机推荐
- udp组播的实现
组播在内核里面对应的一个重要的结构体是ip_mreq,如下: struct ip_mreq { struct in_addr imr_multiaddr; /* IP multicast addres ...
- Quartz快速上手
快速上手你需要干啥: 下载Quartz 安装Quartz 根据你的需要来配置Quartz 开始一个示例应用 下载和安装 The Quartz JAR Files The main Quartz lib ...
- Vue中的model
v-model语法糖: model: 默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event, 但是一些输入类型比如单选框和复选框按钮可能想使用 ...
- Centos6.5安装配置svn服务器
一. yum安装svn服务器 yum -y install subversion 二. 检测安装结果 svnserve --version //显示安装结果,表示安装成功了 三. 创建代码仓库目录 m ...
- mysql安装及相关配置
安装下载 第一种 安装mysql安装包 //www.jb51.net/softs/451120.html 保存root密码 打开系统偏好设置,start mysql server #配置mysql e ...
- 19. Jmeter抓包之浏览器请求
web测试过程中我们经常需要抓包,通常我们使用fiddler或者Charles.但是jmeter也可以抓包,而且非常好用,闲话不多说,下面进入正题.下面用一个例子进行说明 需求:bing首页搜索南京测 ...
- Android - Retrofit 2.0 使用教程(含实例讲解)
链接:https://blog.csdn.net/carson_ho/article/details/73732076
- Mac020--常用插件
Google浏览器常用插件 1.github插件octotree 2.掘金Chrome网上应用商店 2-1.掘金/老司机的神兵利器 2-2.好用的Google插件:来自掘金 3.Gliffy Diag ...
- 五、Zabbix-自动注册
一.Zabbix Serber 1.进入动作界面 配置—>动作—>事件源—>自动注册—>创建动作 2.配置自动注册动作 1.配置动作 2.配置操作 Next step 添加成功 ...
- 2019 我的世界多了一个 Python
大一时学过 C语言,大三时用 C 控制单片机,之后就没有别的和编程的交集了. 大约十天前下定决心学 Python,不开玩笑,版本我选 3. 其实我也不是 100% 的零基础,因为一方面,我学过 C:另 ...