【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息
题目描述

输入
输出
样例输入
8 6
A 2 3
A 3 4
A 3 8
A 8 7
A 6 5
Q 3 8
样例输出
6
题解
LCT维护子树信息
学了大神的LCT维护子树信息的方式,觉得还算好理解,于是自己yy了这道题。
我们知道,在LCT中的Splay Tree中,access某个点并splay到根,那么它的实儿子记录的信息是这条链的信息,并不是我们想要的子树信息。
而所有实儿子和虚儿子的信息才是我们想要求的子树信息。
但是由于虚儿子“儿子认爹,爹不认儿子”的性质,无法在pushup的时候上传信息。
事实上,我们注意到,对于Splay Tree的所有基本操作,除了access和link以外,都不会对虚儿子的信息进行修改。
那么我们每次在添加虚儿子时,顺便把虚儿子的信息也记录到父亲节点中。
这样我们每次调用一个节点时,将它Splay Tree中实儿子的信息,加上它自身的虚儿子的信息,就是我们想要的子树信息。
于是我们对于每个节点记录两个信息:它的总信息和它虚儿子的信息,pushup时更新x的总信息为:x实儿子的总信息+x虚儿子的信息+x本身的信息。
按照这种方法我们来思考这道题,可以发现所求的答案就是一条边两端点的子树大小乘积,我们把某一个端点定为整棵树的根,可以知道整棵树的大小,而根据另一个节点可以知道一个子树的大小,相减即为另一个子树的大小。
具体的实现:
access操作中割断了实边c[1][x],该边变为了虚边,所以应该加到x的虚儿子信息中,加入了实边t,该边不再是虚边,所以应从x的虚儿子信息中减去。
link操作中为了在加入x时同时更新y的信息,需要makeroot(x),makeroot(y),然后连x->y的虚边(实际上只需要access(y)和splay(y))。
其余的操作,和普通的LCT没有任何区别。
代码中需要注意的是,sum[x]存的是总信息(子树大小),si[x]存的是虚儿子信息(子树除了链以外的大小),不要弄混。
#include <cstdio>
#include <algorithm>
#define N 100010
using namespace std;
int fa[N] , c[2][N] , si[N] , sum[N] , rev[N];
char str[5];
void pushup(int x)
{
sum[x] = sum[c[0][x]] + sum[c[1][x]] + si[x] + 1;
}
void pushdown(int x)
{
if(rev[x])
{
int l = c[0][x] , r = c[1][x];
swap(c[0][l] , c[1][l]) , swap(c[0][r] , c[1][r]);
rev[l] ^= 1 , rev[r] ^= 1 , rev[x] = 0;
}
}
bool isroot(int x)
{
return c[0][fa[x]] != x && c[1][fa[x]] != x;
}
void update(int x)
{
if(!isroot(x)) update(fa[x]);
pushdown(x);
}
void rotate(int x)
{
int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
if(!isroot(y)) c[c[1][z] == y][z] = x;
fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
pushup(y) , pushup(x);
}
void splay(int x)
{
update(x);
while(!isroot(x))
{
int y = fa[x] , z = fa[y];
if(!isroot(y))
{
if((c[0][y] == x) ^ (c[0][z] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
int t = 0;
while(x) splay(x) , si[x] += sum[c[1][x]] - sum[t] , c[1][x] = t , pushup(x) , t = x , x = fa[x];
}
void makeroot(int x)
{
access(x) , splay(x) , swap(c[0][x] , c[1][x]) , rev[x] = 1;
}
void split(int x , int y)
{
makeroot(x) , makeroot(y);
}
void link(int x , int y)
{
split(x , y) , fa[x] = y , si[y] += sum[x] , pushup(y);
}
int main()
{
int n , m , i , x , y;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ ) sum[i] = 1;
while(m -- )
{
scanf("%s%d%d" , str , &x , &y);
if(str[0] == 'A') link(x , y);
else split(x , y) , printf("%lld\n" , (long long)sum[x] * (sum[y] - sum[x]));
}
return 0;
}
【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息的更多相关文章
- BZOJ4530[Bjoi2014]大融合——LCT维护子树信息
题目描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够 联通的树上路过它的简单路径的数 ...
- bzoj 4530 [Bjoi2014]大融合——LCT维护子树信息
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4530 LCT维护子树 siz .设 sm[ ] 表示轻儿子的 siz 和+1(1是自己的si ...
- [BJOI2014]大融合 LCT维护子树信息
Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...
- Loj 2230. 「BJOI2014」大融合 (LCT 维护子树信息)
链接:https://loj.ac/problem/2230 思路: 设立siz数组保存虚点信息,sum表示总信息 维护子树信息link操作和access操作需要进行一些改动 可参考博客:https: ...
- bzoj 4530 大融合 —— LCT维护子树信息
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4530 用LCT维护子树 size,就是实边和虚边分开维护: 看博客:https://blog ...
- 大融合——LCT维护子树信息
题目 [题目描述] 小强要在 $N$ 个孤立的星球上建立起一套通信系统.这套通信系统就是连接 $N$ 个点的一个树.这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树 ...
- P4219 [BJOI2014]大融合 LCT维护子树大小
\(\color{#0066ff}{ 题目描述 }\) 小强要在\(N\)个孤立的星球上建立起一套通信系统.这套通信系统就是连接\(N\)个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一 ...
- [BZOJ4530][Bjoi2014]大融合 LCT + 启发式合并
[BZOJ4530][Bjoi2014]大融合 试题描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是 ...
- BZOJ4530:[BJOI2014]大融合(LCT)
Description 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够 联通的树上路过它 ...
随机推荐
- redis执行lua文件
1.编写lua文件 还lua表示循环插入1-100的键为1-100值为1-100的键值对到redis中 for i=0,100 do redis.call("set",i,i) e ...
- Cookie知识点总结
Cookie机制是采用客户端保持Http状态信息的方案. Cookie是在浏览器访问web服务器的某个资源的时候,由web服务器在http响应消息头中附带给浏览器的一个小文本文件. 一旦web服务器保 ...
- iView 的分页结合表格用法
HTML: <Table border stripe ref="selection" :columns="columns" :data="now ...
- java开发JDBC连接数据库代码
JDBC连接数据库,创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 这通过java.lang.Class类的静态方法forName(String className)实 ...
- 斯坦福大学公开课机器学习:advice for applying machine learning - deciding what to try next(设计机器学习系统时,怎样确定最适合、最正确的方法)
假如我们在开发一个机器学习系统,想试着改进一个机器学习系统的性能,我们应该如何决定接下来应该选择哪条道路? 为了解释这一问题,以预测房价的学习例子.假如我们已经得到学习参数以后,要将我们的假设函数放到 ...
- java8 List<对象> 转 Set、Map(高级)
实体类 public class Student { private int id; private String name; private String score; private int cl ...
- rest_framework学习之路
目录 RESTful理解 APIView 序列化组件 视图组件 解析器 认证组件 权限组件 频率组件 分页器 响应器 URL控制器 版本控制器
- bind,apply,call,caller,callee还傻傻分不清楚?
先介绍每个的语法: 1. bind() 语法:fn.bind(thisObj[, arg1[, arg2[, ...]]]) fn:是想要改变this指向的函数 thisObj:表示fn中this指针 ...
- mysql全备份脚本速查
mysql全备份脚本 # 快捷备份方式[root@nb scripts]# cat db.backup.sh #!/bin/bashmysqldump -ubackup -pbackuppwd -P3 ...
- Mybatis分页插件PageHelper
application.properties配置 pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.suppor ...