【刷题】COGS 2701 动态树
★★★☆
输入文件:dynamic_tree.in
输出文件:dynamic_tree.out
简单对比
时间限制:1 s 内存限制:256 MB
【题目描述】
开始时有n个点形成的森林,共m个操作。tp=1时,接下来一个参数u,表示将u所在的树树根变为u。tp=2时,接下来一个参数u,询问以u为根的子树的大小。tp=3时,接下来两个参数u,v,添加一条边(u,v),并将u所在树的根作为两棵树合并后的根。
【输入格式】
第一行两个整数n,m。
接下来m行,每行开头是一个整数tp。tp=1或tp=2时,接下来一个整数u。tp=3时,接下来两个整数(u,v)。
【输出格式】
对于每个询问,你需要输出以u为根的子树大小。
【样例输入】
5 10
3 2 3
3 4 5
3 2 4
2 1
2 5
3 1 2
2 4
1 3
2 1
2 4
【样例输出】
1
1
2
1
2
【数据范围】
n<=200000,m<=400000
【题解】
裸的LCT维护子树信息
操作一直接makeroot
操作二,access后输出点的虚子树信息,把虚子树维护点数+1输出。为什么是虚子树?可以自己画一张图,发现因为是access,所以点把它所有原树中儿子的边全部断掉了,变成虚边,而重边要么没有,要么只有左儿子(满足深度随中序遍历递增),但这左儿子显然深度是小于当前点的,也就是说左儿子是当前点在原树中的父亲(祖先),反正不是儿子,所以不能加实子树信息
操作三,存下之前的rt,然后连边,再makeroot
#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
const int MAXN=200000+10;
int n,m;
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
int ch[MAXN][2],fa[MAXN],rev[MAXN],size[MAXN],Isize[MAXN],stack[MAXN],cnt;
inline bool nroot(int x)
{
return lc(fa[x])==x||rc(fa[x])==x;
}
inline void reverse(int x)
{
std::swap(lc(x),rc(x));
rev[x]^=1;
}
inline void pushup(int x)
{
size[x]=size[lc(x)]+size[rc(x)]+Isize[x]+1;
}
inline void pushdown(int x)
{
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(int x)
{
int f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(int x)
{
cnt=0;
stack[++cnt]=x;
for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
while(cnt)pushdown(stack[cnt--]);
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
pushup(x);
}
inline void access(int x)
{
for(register int y=0;x;x=fa[y=x])
{
splay(x);
Isize[x]+=size[rc(x)];
rc(x)=y;
Isize[x]-=size[rc(x)];
pushup(x);
}
}
inline int findroot(int x)
{
access(x);splay(x);
while(lc(x))pushdown(x),x=lc(x);
splay(x);
return x;
}
inline void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
inline void link(int x,int y)
{
makeroot(x);access(y);splay(y);
fa[x]=y;
Isize[y]+=size[x];
pushup(y);
}
};
LCT T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
freopen("dynamic_tree.in","r",stdin);
freopen("dynamic_tree.out","w",stdout);
read(n);read(m);
while(m--)
{
int opt;
read(opt);
if(opt==1)
{
int u;
read(u);
T.makeroot(u);
}
if(opt==2)
{
int u;
read(u);
T.access(u);
write(T.Isize[u]+1,'\n');
}
if(opt==3)
{
int u,v,rt;
read(u);read(v);
rt=T.findroot(u);
T.link(u,v);T.makeroot(rt);
}
}
return 0;
}
【刷题】COGS 2701 动态树的更多相关文章
- hdu-1540线段树刷题
title: hdu-1540线段树刷题 date: 2018-10-18 19:55:21 tags: acm 刷题 categories: ACM-线段树 概述 哇,,,这道线段树的题可以说是到目 ...
- hdu-5023线段树刷题
title: hdu-5023线段树刷题 date: 2018-10-18 13:32:13 tags: acm 刷题 categories: ACM-线段树 概述 这道题和上次做的那道染色问题一样, ...
- poj-2777线段树刷题
title: poj-2777线段树刷题 date: 2018-10-16 20:01:07 tags: acm 刷题 categories: ACM-线段树 概述 这道题是一道线段树的染色问题,,, ...
- zoj-1610线段树刷题
title: zoj-1610线段树刷题 date: 2018-10-16 16:49:47 tags: acm 刷题 categories: ACM-线段树 概述 这道题是一道简单的线段树区间染色问 ...
- PKUWC&SC 2018 刷题记录
PKUWC&SC 2018 刷题记录 minimax 线段树合并的题,似乎并不依赖于二叉树. 之前写的草率的题解在这里:PKUWC2018 minimax Slay the Spire 注意到 ...
- 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- bzoj2049-洞穴勘测(动态树lct模板题)
Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...
- bzoj 2759一个动态树好题
真的是动态树好题,如果把每个点的父亲设成p[x],那么建出来图应该是一个环套树森林,拆掉一条边,就变成了动态树,考虑维护什么,对于LCT上每个节点,维护两组k和b,一组是他到他父亲的,一组是他LCT子 ...
- BZOJ2759 一个动态树好题 LCT
题解: 的确是动态树好题 首先由于每个点只有一个出边 这个图构成了基环内向树 我们观察那个同余方程组 一旦形成环的话我们就能知道环上点以及能连向环上点的值是多少了 所以我们只需要用一种结构来维护两个不 ...
随机推荐
- 年薪30W的软件测试“老司机”工作经验
这几天,新入职的小MM提议“老司机”们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. 测试阶段划分 1. ...
- c语言数字图像处理(七):频率域滤波
代码运行了两个小时才出的结果,懒得测试了,这一部分先鸽了,等对DFT算法进行优化后再更
- Python 之Memcache中间件
一.引子 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载,它通过在内存中缓存数据和减少读取数据库的次数,从而提高动态数据库驱动网站的速度.Memcache ...
- lua中table的常用方法
转载:https://blog.csdn.net/Fenglele_Fans/article/details/83627021 1:table.sort() language = {"lua ...
- python基础教程:包的创建及导入
包是一种通过用“带点号的模块名”来构造 Python 模块命名空间的方法. 例如,模块名 A.B 表示 A 包中名为 B 的子模块.正如模块的使用使得不同模块的作者不必担心彼此的全局变量名称一样,使用 ...
- 08-matplotlib-颜色与样式
import numpy as np import matplotlib.pyplot as plt ''' 颜色: - 八种内置默认颜色, 缩写 b :blue g :green r :red c ...
- linux压缩相关
tar命令 tar是打包,即把好多东西放在一个大文件里面,之后再压缩:当然也可以解包 tar的几个参数说明: -c 创建一个新的包 -x 将包里的文件还原出来 -t 显示包内文件的列表 -f 指定要处 ...
- Java面试中的Spring方面问题
1.一般问题 1.1. 不同版本的 Spring Framework 有哪些主要功能? VersionFeatureSpring 2.5发布于 2007 年.这是第一个支持注解的版本.Spring 3 ...
- 150314 解决老师给二柱子出的问题 之 ver1.0
一个晚上的成果,效果捉鸡,代码很乱.暂定ver1.0 //Powered by LZR! 2015.3.14#include<iostream> #include<stdio.h&g ...
- java 线程的简单理解
想要实现线程可以继承Thread也可以实现接口runnable,在类中重写 run()方法在主函数调用start方法就可以开辟线程. 对于java对象都有一个wait()和notify().notif ...