Luogu 3690 Link Cut Tree

  • \(LCT\) 模板题.可以参考讲解和这份码风(个人认为)良好的代码.
  • 注意用 \(set\) 来维护实际图中两点是否有直接连边,否则无脑 \(Link/Cut\) 会崩掉.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
int x=0;
bool pos=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
pos=0;
for(;isdigit(ch);ch=getchar())
x=x*10+ch-'0';
return pos?x:-x;
}
const int MAXN=3e5+10;
struct node{
int val,sum,rev;
int ch[2],fa;
node()
{
rev=0;
val=sum=0;
}
}tree[MAXN];//splay以原图中的深度为关键字.
set<int> Link[MAXN];//维护两点是否有边相连
int n,m,stk[MAXN],tp=0;
#define root tree[x]
#define lson tree[tree[x].ch[0]]
#define rson tree[tree[x].ch[1]]
void pushup(int x)
{
root.sum=lson.sum^root.val^rson.sum;
}
void inverse(int x)
{
swap(tree[x].ch[0],tree[x].ch[1]);
root.rev^=1;
}
void pushdown(int x)
{
if(root.rev)
{
if(root.ch[0])
inverse(root.ch[0]);
if(root.ch[1])
inverse(root.ch[1]);
root.rev=0;
}
}
bool isroot(int x)
{
return tree[root.fa].ch[0]!=x && tree[root.fa].ch[1]!=x;
}
void rotate(int x)
{
int y=tree[x].fa,z=tree[y].fa;
int k=tree[y].ch[1]==x;
if(!isroot(y))
tree[z].ch[tree[z].ch[1]==y]=x;
tree[x].fa=z;//splay中,根的父亲是原图中链顶(该节点)的父亲
tree[y].ch[k]=tree[x].ch[k^1];
tree[tree[x].ch[k^1]].fa=y;
tree[x].ch[k^1]=y;
tree[y].fa=x;
pushup(y);
}
void splay(int x)
{
stk[++tp]=x;
for(int pos=x;!isroot(pos);pos=tree[pos].fa)
stk[++tp]=tree[pos].fa;
while(tp)
pushdown(stk[tp--]);//因为要从下往上转,所以先将从x到splay根节点上的标记全部下传
while(!isroot(x))
{
int y=tree[x].fa,z=tree[y].fa;
if(!isroot(y))
(tree[y].ch[0]==x)^(tree[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
}
void Access(int x)
{
for(int y=0;x;y=x,x=tree[x].fa)
{
splay(x);
tree[x].ch[1]=y;
pushup(x);
}
}
void makeroot(int x)
{
Access(x);
splay(x);
inverse(x);
}
int findroot(int x)
{
Access(x);
splay(x);//翻转后找深度最小的,就是原来深度最大的.
while(tree[x].ch[0])
x=tree[x].ch[0];
return x;
}
void split(int x,int y)
{
makeroot(x);
Access(y);//x到y是一颗splay
splay(y);//然后就是y及其左子树存储的信息了. (实际上就是y,因为它没有右子树)
}
void link(int x,int y)
{
if(Link[x].find(y)!=Link[x].end())
return;
makeroot(x);
tree[x].fa=y;//连一条虚边
Link[x].insert(y);
Link[y].insert(x);
}
void cut(int x,int y)
{
if(Link[x].find(y)==Link[x].end())
return;
split(x,y);//在splay中从y一直往左走到x.
tree[y].ch[0]=0;
tree[x].fa=0;
Link[x].erase(y);
Link[y].erase(x);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;++i)
tree[i].val=tree[i].sum=read();//原图编号即splay标号
while(m--)
{
int op=read(),x=read(),y=read();
if(op==0)
{
split(x,y);
printf("%d\n",tree[y].sum);
}
else if(op==1)
{
link(x,y);
}
else if(op==2)
{
cut(x,y);
}
else
{
Access(x);
splay(x);//这样不用修改splay中其他节点信息
tree[x].val=y;
pushup(x);
}
}
return 0;
}

Luogu 3690 Link Cut Tree的更多相关文章

  1. (RE) luogu P3690 【模板】Link Cut Tree

    二次联通门 : luogu P3690 [模板]Link Cut Tree 莫名RE第8个点....如果有dalao帮忙查错的话万分感激 #include <cstdio> #includ ...

  2. Link Cut Tree 总结

    Link-Cut-Tree Tags:数据结构 ##更好阅读体验:https://www.zybuluo.com/xzyxzy/note/1027479 一.概述 \(LCT\),动态树的一种,又可以 ...

  3. 洛谷P3690 [模板] Link Cut Tree [LCT]

    题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...

  4. link cut tree 入门

    鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...

  5. Codeforces Round #339 (Div. 2) A. Link/Cut Tree 水题

    A. Link/Cut Tree 题目连接: http://www.codeforces.com/contest/614/problem/A Description Programmer Rostis ...

  6. Link/cut Tree

    Link/cut Tree 一棵link/cut tree是一种用以表示一个森林,一个有根树集合的数据结构.它提供以下操作: 向森林中加入一棵只有一个点的树. 将一个点及其子树从其所在的树上断开. 将 ...

  7. 洛谷P3690 Link Cut Tree (模板)

    Link Cut Tree 刚开始写了个指针版..调了一天然后放弃了.. 最后还是学了黄学长的板子!! #include <bits/stdc++.h> #define INF 0x3f3 ...

  8. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  9. bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门

    link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isro ...

随机推荐

  1. 常见HTTP状态(304,)

    一.1XX(临时响应) 表示临时响应并需要请求者继续执行操作的状态码. 100(继续) 请求者应当继续提出请求.服务器返回此代码表示:已经收到请求的第一部分,正在等待其余部分. 101(切换协议) 请 ...

  2. QtCreator的中如何使用第三方依赖库

    > https://blog.csdn.net/e5Max/article/details/9840331 ```LIBS += -L/usr/local/lib -lmath  ``` ``` ...

  3. [Vue]组件——.sync 修饰符实现对prop 进行“双向绑定”

    一.同时设置1个 prop 1.以 update:my-prop-name 的模式触发事件,如对于title属性: this.$emit('update:title', newTitle) 2.然后父 ...

  4. Selenium元素定位问题

    定位元素时,遇到一些诡异事件: 明明就是通过ID定位的,但是就是没有定位到该元素呢? 1.通过element.find_elements_by_xxx()获取该元素的个数,试试是否有获取到元素,0个表 ...

  5. dapper-dot-net/Dapper NET40/SqlMapper.cs

    /* License: http://www.apache.org/licenses/LICENSE-2.0 Home page: http://code.google.com/p/dapper-do ...

  6. Verilog HDL Test Bench

    As digital systems becomes more complex,it becomes increasingly important to verify the functionalit ...

  7. UVA-1615 Highway (贪心,区间选点)

    题目大意:有一条沿x轴正方向,长为L的高速公路,n个村庄,要求修建最少的公路出口数目,使得每个村庄到出口的距离不大于D. 题目分析:区间选点问题.在x轴上,到每个村庄距离为D的点有两个(超出范围除外) ...

  8. crontab执行定时任务

    在linux下面使用命令crontab -e  编辑任务: [adv@localhost]$ crontab -e 之后开始编辑任务 * * * * * cd /home/adv/work/cutte ...

  9. FreeMarker初探--介绍

    FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP.它不仅可以用作表现层的实现 ...

  10. JDK的KeyTool和KeyStore等加密相关

    Keytool是一个有效的安全钥匙和证书的管理工具. Java 中的 keytool.exe (位于JDK\Bin下)可以用来创建数字证书,所有的数字证书是以一条一条(用别名区别,不区分大小)地存储在 ...