P4219 [BJOI2014]大融合
动态维护森林
显然考虑 $LCT$
但是发现询问求的是子树大小,比较不好搞
维护 $sum[x]$ 表示节点 $x$ 的子树大小,$si[x]$ 表示 $x$ 的子树中虚儿子的子树大小和
那么 $pushup$ 可以这样写:
inline void pushup(int x) { sum[x]=sum[c[x][]]+sum[c[x][]]+si[x]+; }
考虑什么时候 $si$ 会变
首先对于 $rotate,splay$ 因为都是对一条实链搞,所以对虚边没影响
然后考虑 $access$ ,发现边的虚实有改变
原本 $x$ 的右儿子变成另一个节点,那么要记得更新
然后 $makeroot$ ,发现我们翻转的是一条实链,所以同样不会对虚边产生影响
然后 $split$ ,调用了 $makeroot,access,splay$ 这些之前都考虑过了
然后 $link$,发现多了一条虚边,所以要记得更新一下
然后 $cut$,因为断的是实边,所以不会改变
那么询问时只要 $makeroot(x),access(y),splay(y)$ ,然后 $y$ 的右儿子就是 $x$ ,输出 $(si[x]+1)*(si[y]+1)$ 即可
具体看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+;
int c[N][],fa[N],si[N],sum[N];
bool rev[N];//维护的是延时标记
inline void pushup(int x) { sum[x]=sum[c[x][]]+sum[c[x][]]+si[x]+; }
inline void pushdown(int x)
{
if(!x||!rev[x]) return;
int &lc=c[x][],&rc=c[x][];
swap(lc,rc); rev[x]=;
if(lc) rev[lc]^=;
if(rc) rev[rc]^=;
}
inline void rever(int x) { rev[x]^=; pushdown(x); }
inline bool notroot(int x) { return (c[fa[x]][]==x)|(c[fa[x]][]==x); }
inline void rotate(int x)
{
int y=fa[x],z=fa[y],d=(c[y][]==x);
if(notroot(y)) c[z][c[z][]==y]=x;
fa[x]=z; fa[y]=x; fa[c[x][d^]]=y;
c[y][d]=c[x][d^]; c[x][d^]=y;
pushup(y); pushup(x);
}
void push_tag(int x)
{
if(notroot(x)) push_tag(fa[x]);
else pushdown(x);
pushdown(c[x][]); pushdown(c[x][]);
}
inline void splay(int x)
{
push_tag(x);
while(notroot(x))
{
int y=fa[x],z=fa[y];
if(notroot(y))
{
if(c[z][]==y ^ c[y][]==x) rotate(x);
else rotate(y);
}
rotate(x);
}
}
inline void access(int x)
{
for(int y=;x;y=x,x=fa[x])
{
splay(x); si[x]+=(sum[c[x][]]-sum[y]);//记得更新si
c[x][]=y; pushup(x);
}
}
inline void makeroot(int x) { access(x); splay(x); rever(x); }
inline void split(int x,int y) { makeroot(x); access(y); splay(y); }
inline void link(int x,int y) { split(x,y); fa[x]=y; si[y]+=sum[x];/*更新si*/ pushup(y); }
inline void query(int x,int y)
{
split(x,y);//和makeroot(x),access(y),splay(y)是同样的写法
printf("%lld\n",1ll*(si[x]+)*(si[y]+));
}
int n,m;
int main()
{
int a,b; char s[];
n=read(); m=read();
for(int i=;i<=n;i++) sum[i]=;
while(m--)
{
scanf("%s",s); a=read(),b=read();
if(s[]=='A') link(a,b);
else query(a,b);
}
return ;
}
P4219 [BJOI2014]大融合的更多相关文章
- P4219 [BJOI2014]大融合(LCT)
P4219 [BJOI2014]大融合 对于每个询问$(u,v)$所求的是 ($u$的虚边子树大小+1)*($v$的虚边子树大小+1) 于是我们再开个$si[i]$数组表示$i$的虚边子树大小,维护一 ...
- 洛谷 P4219 [BJOI2014]大融合 解题报告
P4219 [BJOI2014]大融合 题目描述 小强要在\(N\)个孤立的星球上建立起一套通信系统.这套通信系统就是连接\(N\)个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的 ...
- 洛谷P4219 - [BJOI2014]大融合
Portal Description 初始有\(n(n\leq10^5)\)个孤立的点,进行\(Q(Q\leq10^5)\)次操作: 连接边\((u,v)\),保证\(u,v\)不连通. 询问有多少条 ...
- 洛谷P4219 [BJOI2014]大融合(LCT,Splay)
LCT维护子树信息的思路总结与其它问题详见我的LCT总结 思路分析 动态连边,LCT题目跑不了了.然而这题又有点奇特的地方. 我们分析一下,查询操作就是要让我们求出砍断这条边后,x和y各自子树大小的乘 ...
- 洛谷P4219 [BJOI2014]大融合(LCT)
LCT维护子树信息的思路总结与其它问题详见我的LCT总结 思路分析 动态连边,LCT题目跑不了了.然而这题又有点奇特的地方. 我们分析一下,查询操作就是要让我们求出砍断这条边后,x和y各自子树大小的乘 ...
- P4219 [BJOI2014]大融合 LCT维护子树大小
\(\color{#0066ff}{ 题目描述 }\) 小强要在\(N\)个孤立的星球上建立起一套通信系统.这套通信系统就是连接\(N\)个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一 ...
- 洛谷 P4219 [BJOI2014]大融合
查询,就相当于先删去这条边,然后查询边的两个端点所在连通块大小,乘起来得到答案,然后再把边加回去 可以用线段树分治做 #pragma GCC optimize("Ofast") # ...
- luogu P4219 [BJOI2014]大融合
题解:原来LCT也能维护子树信息,我太Naive了 用LCT维护当前子树节点个数 具体做法维护siz[x]=当前Splay子树和指向当前Splay子树的虚边所代表的节点个数 auxsiz[x]=指向x ...
- [BZOJ4530][Bjoi2014]大融合 LCT + 启发式合并
[BZOJ4530][Bjoi2014]大融合 试题描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是 ...
随机推荐
- ubuntu18.04 蓝牙打开无效,解决办法升级内核
http://kernel.ubuntu.com/~kernel-ppa/mainline/ 上面的链接是linux内核版本, 蓝牙不管用可能是linux内核版本过低,本人亲自实验过, 升级到4.20 ...
- GROUP BY ROLLUP和CUBE 用法
ROLLUP和CUBE 用法 Oracle的GROUP BY语句除了最基本的语法外,还支持ROLLUP和CUBE语句. 如果是Group by ROLLUP(A, B, C)的话 ...
- 690. Employee Importance员工权限重要性
[抄题]: You are given a data structure of employee information, which includes the employee's unique i ...
- mvc json 日期问题的最简单解决方法
1.首先编写BaseController这个类,需要引入Newtonsoft.Json.dll程序集 using System;using System.Collections.Generic;usi ...
- redis内存优化方法
先来认识2个redis配置参数 hash-max-ziplist-entries : hash内部编码压缩列表的最大值,默认512 hash-max-zipmap-value : hash内部编码压缩 ...
- JSP+JDBC实现在可视化页面中插入数据到SQL数据库
原创 本篇博客创建一个如下图所示的JSP页面,将用户填入的数据插入到对应的数据库中. JSP页面代码: <%@ page language="java" contentTyp ...
- 煤球数目——第七届蓝桥杯C语言B组(省赛)第一题
原创 煤球数目 有一堆煤球,堆成三角棱锥形.具体:第一层放1个,第二层3个(排列成三角形),第三层6个(排列成三角形),第四层10个(排列成三角形),....如果一共有100层,共有多少个煤球? 请填 ...
- fabric Clone
记录下: var newObj = fabric.util.object.clone(obj); decDoc.dropCanvas.add(newObj., top: }));
- c#递归理解
什么是递归函数? 任何一个方法既可以调用其他方法又可以调用自己,而当这个方法调用自己时,我们就叫它递归函数或者递归方法! 说白了,就是调用自己. 通常递归有两个特点: 1.递归方法一直会调用自 ...
- hbuilder h5 原生socket
在网上搜索了很多资料都不行,要么就是不能发送数据,要么就不能接收数据,使用如下的方法可以接收数据,一个一个字节接收: 有部分限制是需要明确知道要接收多少个字节,否则容易出现接收异常.. var tes ...