题目链接 BZOJ

洛谷

详见这

很明显题目是要求去掉一条边后两边子树sz[]的乘积。

LCT维护的是链的信息,那么子树呢?

我们用s_i[x]来记录轻边连向x的子树的和(记作虚儿子),那么sum[x]更新时就是sum[lson]+sum[rson]+val[x]+s_i[x]。

现在需要s_i[x],考虑什么时候会影响它。

Splay()影响的只是节点在辅助树Splay中的相对位置,并不会对树中的信息产生影响。

Access()需要更改右儿子,即加上一个虚儿子加上一个实儿子,对应更新即可,如果只需要维护sum之类不需要Update()(一加一减)。

Make_root()无影响。虽然使整棵树形态都发生了变化,但这一操作并不直接用来获取信息。

Split()不需要考虑(仅是调用函数)。

Find_root()无影响。

Link()后y多了一个虚儿子,那么sum[y],s_i[y]加上x。这一步之前要将y旋到根(Access(y),Splay(y)),否则y以上的部分不会更新。

Cut()无影响。虽然少了个儿子,但这一操作不会用来直接获取信息,下次获取信息时会更新,不会影响正确性。

这样答案就是x,y两边s_i+1的乘积(分离出路径后实的就是x->y了,再加上自己),或是(y为根时)sz[x]*(sz[y]-sz[x])

//3264kb	1380ms
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=1e5+5; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
namespace LCT
{
#define lson son[x][0]
#define rson son[x][1] int fa[N],son[N][2],sz[N],sz_i[N],sk[N];
bool tag[N];
inline void Update(int x){
sz[x]=sz[lson]+sz[rson]+1+sz_i[x];
}
inline bool n_root(int x){
return son[fa[x]][0]==x||son[fa[x]][1]==x;
}
inline void Rev(int x){
std::swap(lson,rson), tag[x]^=1;
}
inline void PushDown(int x){
if(tag[x]) Rev(lson),Rev(rson),tag[x]=0;
}
void Rotate(int x)
{
int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
if(n_root(a)) son[b][son[b][1]==a]=x;
if(son[x][r]) fa[son[x][r]]=a;
fa[a]=x, fa[x]=b, son[a][l]=son[x][r], son[x][r]=a;
Update(a);
}
void Splay(int x)
{
int t=1,a=x,b; sk[1]=x;//
while(n_root(a)) sk[++t]=a=fa[a];
while(t) PushDown(sk[t--]);
while(n_root(x))
{
a=fa[x], b=fa[a];
if(n_root(a)) Rotate(son[a][1]==x^son[b][1]==a?x:a);
Rotate(x);
}
Update(x);
}
void Access(int x){
for(int pre=0; x; x=fa[pre=x])
{
Splay(x);
sz_i[x]+=sz[rson], sz_i[x]-=sz[rson=pre];
// Update(x);
}
}
void Make_root(int x){
Access(x), Splay(x), Rev(x);
}
void Split(int x,int y){
Make_root(x), Access(y), Splay(y);
}
void Link(int x,int y){
Split(x,y), sz_i[fa[x]=y]+=sz[x], Update(y);//更新!
}
long long Query(int x,int y){
Split(x,y); return 1ll*(sz_i[x]+1)*(sz_i[y]+1);//1ll*sz[x]*(sz[y]-sz[x]);
}
} int main()
{
int n=read(),q=read(),x,y; char opt[3];
for(int i=1; i<=n; ++i) LCT::sz[i]=1;
while(q--)
{
scanf("%s",opt),x=read(),y=read();
if(opt[0]=='A') LCT::Link(x,y);
else printf("%lld\n",LCT::Query(x,y));
}
return 0;
}

BZOJ.4530.[BJOI2014]大融合(LCT)的更多相关文章

  1. bzoj 4530 [Bjoi2014]大融合——LCT维护子树信息

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4530 LCT维护子树 siz .设 sm[ ] 表示轻儿子的 siz 和+1(1是自己的si ...

  2. BZOJ:4530: [Bjoi2014]大融合

    4530: [Bjoi2014]大融合 拿这题作为lct子树查询的练手.本来以为这会是一个大知识点,结果好像只是一个小技巧? 多维护一个虚边连接着的子树大小即可. #include<cstdio ...

  3. bzoj 4530: [Bjoi2014]大融合【LCT】

    新姿势,一般来讲LCT只能维护splay重边里的数据,而这里要求维护整颗子树的size 多维护一个sq表示当前点轻儿子的size和,si表示包括轻重边的整颗子树的大小 然后需要改sq的地方是link和 ...

  4. 【刷题】BZOJ 4530 [Bjoi2014]大融合

    Description 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够 联通的树上路过它 ...

  5. [BZOJ4530][Bjoi2014]大融合 LCT + 启发式合并

    [BZOJ4530][Bjoi2014]大融合 试题描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是 ...

  6. [BJOI2014]大融合(LCT)

    题面 luogu bzoj是权限题.. 题解 \(LCT\)维护子树信息 因为\(LCT\)中有一些虚子树,\(splay\)维护不了. 所以要新开一个数组来记录 然后注意\(link\)时 是先\( ...

  7. 【BZOJ】4530: [Bjoi2014]大融合

    [题意]给定n个点的树,从无到有加边,过程中动态询问当前图某条边两端连通点数的乘积,n<=10^5. [算法]线段树合并+并查集 (||LCT(LCT维护子树信息 LCT维护子树信息(+启发式合 ...

  8. 【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息

    题目描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量 ...

  9. Luogu4219 BJOI2014 大融合 LCT

    传送门 题意:写一个数据结构,支持图上连边(保证图是森林)和询问一条边两端的连通块大小的乘积.$\text{点数.询问数} \leq 10^5$ 图上连边,$LCT$跑不掉 支持子树$size$有点麻 ...

随机推荐

  1. 【转】shell编程下 特殊变量、test / [ ]判断、循环、脚本排错

    [转]shell编程下 特殊变量.test / [ ]判断.循环.脚本排错 第1章 shell中的特殊变量 1.1 $# $# 表示参数的个数 1.1.1 [示例]脚本内容 [root@znix ~] ...

  2. python flask安装

    windows环境上,打开命令行,输入pip  list  检查列表中是否安装过flask 安装flask命令:pip install flask 出现Successfully installed等提 ...

  3. Python-ccs动画及阴影

    动画及阴影 0. 什么时候该用什么布局 <!-- 定位布局: 以下两种布局不易解决的问题, 盒子需要脱离文档流处理 --> <!-- 浮动布局: 一般有block特性的盒子,水平排列 ...

  4. C#中Convert.ToInt32、int.TryParse、(int)和int.Parse四者的区别

    Convert.ToInt32.(int)和int.Parse三者的区别: 首先:Convert.ToInt32 适合将object类类型转换成int类型,如Convert.ToInt32(sessi ...

  5. 测试开发之Django——No6.Django模板中的标签语言

    模板中的标签语言 1.if/else {% if  %} 标签检查(evaluate)一个变量,如果这个变量为真(即:变量存在,非空,不是布尔值假),系统会显示在{% if  %} 和 {% endi ...

  6. LeetCode(37): 每k个一组翻转链表

    Hard! 题目描述: 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一 ...

  7. bootstrap----屏幕大小切换

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. iOS中按钮点击事件处理方式

    写在前面 在iOS开发中,时常会用到按钮,通过按钮的点击来完成界面的跳转等功能.按钮事件的实现方式有多种,其中 较为常用的是目标-动作对模式.但这种方式使得view与controller之间的耦合程度 ...

  9. 步步为营-64-进程&线程

    1 进程 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; us ...

  10. java判断给定路径或URL下的文件或文件夹是否存在?

    if (file.exists()) { 来判断这是不是一个文件. file.isDirectory() 来判断这是不是一个文件夹. 1.File testFile = new File(testFi ...