【刷题】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
题解: 的确是动态树好题 首先由于每个点只有一个出边 这个图构成了基环内向树 我们观察那个同余方程组 一旦形成环的话我们就能知道环上点以及能连向环上点的值是多少了 所以我们只需要用一种结构来维护两个不 ...
随机推荐
- vue.js和vue-router和vuex快速上手知识
vue.js和vue-router和vuex快速上手知识 一直以来,认为vue相比react而言,学习成本会更低,会更简单,但最近真正接触后,发现vue的各方面都有做一些客户化的优化,有一些亮点,但也 ...
- Revit开发-设置对象样式
最近需要读取RVT项目样板一些对象样式,翻了一下API,查找到下面的情况:
- RSA详解
RSA RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作.RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥 ...
- 九九乘法表的python复习
九九开始的复习 这周复习之前的学的知识关于range函数,gormat函数,print的使用总结一下 从一个小例子开始,开始我的回顾吧, 大家都是从那个九九乘法表开始的数学之旅,从一一得一,开始了我们 ...
- [笔试]CVTE 2019提前批 Windows应用开发笔试
不定项选择(x20) 数据结构 以abcdefg的顺序入栈,不可能出现的出栈顺序 一棵二叉树给出中序遍历和后序遍历结果,求左子树的节点数 操作系统 Linux中用什么指令可以找到文件中所有以" ...
- Docker入门与实践之 Dockerfile 语法详解
一.Dockerfile 概述 Dockerfile是docker程序的解释脚本文件,Dockerfile 是一条一条的指令,Docker程序将dockerfile中的一条条指令编译成Linux可执行 ...
- SSZipArchive解压失败的原因
SSZipArchive 解压失败的原因是路径不对解压失败后,修正路径后再次解压就会出现解压失败的情况,代理方法也不会走也没有日志输出.解决方法就是删除手机上的软件再次运行就可以了.这个问题也就在内部 ...
- SQL面经汇总
转载链接:https://www.nowcoder.com/discuss/95812 目前的打算是还要写一个假设检验的汇总和机器学习的汇总. 之前写的概率论汇总: https://www.nowco ...
- 【Py大法系列--01】20多行代码生成你的微信聊天机器人
前言 近期Stack Overflow公布了一项调查显示,Python已经成了发展最快的主流编程语言,Python搭乘着数据科学和机器学习以及人工智能的浪潮,席卷了整个技术圈.越来越多的人想了解.想学 ...
- PSP Daily软件beta版本——基于NABCD评论,及改进建议
1.根据(不限于)NABCD评论作品的选题: 此软件的用户人群较为明确,即:用户(软件工程课上学生)记录例行报告.写每周PSP表格和统计的需求.潜在用户还有未来该课堂的学生和需要用PSP方法记录任务完 ...