题目链接

LCT(良心总结)

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=3e5+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],val[N],sum[N],son[N][2],sk[N];
bool tag[N];
inline void Update(int x){
sum[x]=sum[lson]^sum[rson]^val[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;
}
inline bool n_root(int x){
return son[fa[x]][0]==x||son[fa[x]][1]==x;
}
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), Update(x);
}
void Splay(int x)
{
int t=1,a=x,b; sk[1]=x;
while(n_root(a)) sk[++t]=a=fa[a];//别写成while(fa[x])!
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])//pre=x老漏。。
Splay(x), 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);
}
int Find_root(int x)
{
Access(x), Splay(x);
while(lson) x=lson;
// Splay(x);//需要保证复杂度?
return x;
}
// int Get_fa(int x){
// while(fa[x]) x=fa[x];
// return x;
// }
// void Link(int x,int y){
// if(Get_fa(x)!=Get_fa(y)) Make_root(x),fa[x]=y;//Get_fa()有点慢啊
// }
void Link(int x,int y)
{
Make_root(x);
if(Find_root(y)!=x) fa[x]=y;//连的是轻边!不要加rson=y;
}
void Cut(int x,int y)
{
Make_root(x);
if(Find_root(y)==x&&fa[x]==y&&!rson)
fa[x]=son[y][0]=0, Update(y);
// if(Find_root(y)==x&&fa[y]==x&&!son[y][0])//若Find_root()中把根又转回去了
// fa[y]=rson=0, Update(x);
}
} int main()
{
int n=read(),m=read();
for(int i=1; i<=n; ++i) LCT::val[i]=read();
int opt,x,y;
while(m--)
{
opt=read(),x=read(),y=read();
if(!opt) LCT::Split(x,y), printf("%d\n",LCT::sum[y]);
else if(opt==1) LCT::Link(x,y);
else if(opt==2) LCT::Cut(x,y);
else LCT::Splay(x), LCT::val[x]=y;/*sum[y]^=val[x]^y, val[x]=y*/ //这步在Split()(查询时)的Splay()中 最后还会Update()
}
return 0;
}

第二次(2018.4.5):

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=3e5+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],sum[N],val[N],sk[N];
bool rev[N];
inline void Update(int x){
sum[x]=sum[lson]^sum[rson]^val[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), rev[x]^=1;
}
inline void PushDown(int x){
if(rev[x]) Rev(lson),Rev(rson),rev[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; sk[1]=x;
while(n_root(a)) sk[++t]=a=fa[a];
while(t) PushDown(sk[t--]);
while(n_root(x))
{
if(n_root(a=fa[x])) Rotate(son[a][1]==x^son[fa[a]][1]==a?x:a);
Rotate(x);
}
Update(x);
}
void Access(int x){
for(int pre=0; x; x=fa[pre=x])
Splay(x), 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);
}
int Find_root(int x)
{
Access(x), Splay(x);
while(lson) x=lson;
return x;
}
void Link(int x,int y)
{
Make_root(x);
if(Find_root(y)!=x) fa[x]=y;
}
void Cut(int x,int y)
{
Make_root(x);
if(Find_root(y)==x&&fa[x]==y&&!rson)
fa[x]=son[y][0]=0, Update(y);
}
}
using namespace LCT; int main()
{
int n=read(),m=read(),opt,x,y;
for(int i=1; i<=n; ++i) val[i]=read();
while(m--)
switch(opt=read(),x=read(),y=read(),opt)
{
case 0: Split(x,y),printf("%d\n",sum[y]); break;
case 1: Link(x,y); break;
case 2: Cut(x,y); break;
case 3: Splay(x), val[x]=y; break;
}
return 0;
}

第三次(2018.6.28):竟然快了那么多,好像没什么太大变化啊。。

//592ms	3.76MB
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 150000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=3e5+5; char IN[MAXIN],*SS=IN,*TT=IN;
namespace LCT
{
#define lson son[x][0]
#define rson son[x][1]
int fa[N],son[N][2],val[N],sum[N],sk[N];
bool rev[N]; inline void Update(int x){
sum[x]=sum[lson]^sum[rson]^val[x];
}
inline void Rev(int x){
std::swap(lson,rson), rev[x]^=1;
}
inline void PushDown(int x){
if(rev[x]) Rev(lson), Rev(rson), rev[x]=0;
}
inline bool n_root(int x){
return son[fa[x]][0]==x||son[fa[x]][1]==x;
}
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[x]=b, fa[a]=x, son[a][l]=son[x][r], son[x][r]=a;
Update(a);
}
void Splay(int x)
{
int a=x,t=1; sk[1]=x;
while(n_root(a)) sk[++t]=a=fa[a];
while(t) PushDown(sk[t--]);
while(n_root(x))
{
if(n_root(a=fa[x])) Rotate(son[a][1]==x^son[fa[a]][1]==a?x:a);
Rotate(x);
}
Update(x);
}
void Access(int x){
for(int pre=0; x; x=fa[pre=x])
Splay(x), 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);
}
int Find_root(int x)
{
Access(x), Splay(x);
while(lson) x=lson;
return x;
}
void Link(int x,int y)
{
Make_root(x);
if(Find_root(y)!=x) fa[x]=y;
}
void Cut(int x,int y)
{
Make_root(x);
if(Find_root(y)==x&&!rson&&fa[x]==y) son[y][0]=fa[x]=0, Update(y);
}
}
using namespace LCT; 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;
} int main()
{
int n=read(), m=read();
for(int i=1; i<=n; ++i) val[i]=read();
int opt,x,y;
while(m--){
switch(opt=read(),x=read(),y=read(),opt){
case 0: Split(x,y), printf("%d\n",sum[y]); break;
case 1: Link(x,y); break;
case 2: Cut(x,y); break;
case 3: Splay(x), val[x]=y; break;
}
}
return 0;
}

19.4.5

//520ms	2984KB
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=3e5+5; char IN[MAXIN],*SS=IN,*TT=IN;
struct LCT
{
#define ls son[x][0]
#define rs son[x][1]
int fa[N],son[N][2],sum[N],val[N],sk[N];
bool rev[N];
inline void Update(int x)
{
sum[x]=sum[ls]^sum[rs]^val[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(ls,rs), rev[x]^=1;
}
inline void PushDown(int x)
{
if(rev[x]) Rev(ls), Rev(rs), rev[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[x]=b, fa[a]=x, son[a][l]=son[x][r], son[x][r]=a;
Update(a);
}
void Splay(int x)
{
int t=1,a=x; sk[1]=a;
while(n_root(a)) sk[++t]=a=fa[a];
while(t) PushDown(sk[t--]);
while(n_root(x))
{
if(n_root(a=fa[x])) Rotate(son[a][0]==x^son[fa[a]][0]==a?x:a);
Rotate(x);
}
Update(x);
}
void Access(int x)
{
for(int pre=0; x; x=fa[pre=x])
Splay(x), rs=pre, Update(x);
}
void MakeRoot(int x)
{
Access(x), Splay(x), Rev(x);
}
void Split(int x,int y)
{
MakeRoot(x), Access(y), Splay(y);
}
int FindRoot(int x)
{
Access(x), Splay(x);
while(ls) x=ls;
return x;
}
void Link(int x,int y)
{
MakeRoot(x);
if(FindRoot(y)!=x) fa[x]=y;
}
void Cut(int x,int y)
{
MakeRoot(x);
if(FindRoot(y)==x&&fa[x]==y&&!rs) fa[x]=son[y][0]=0, Update(y);
}
}T; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
} int main()
{
int n=read(),q=read();
for(int i=1; i<=n; ++i) T.val[i]=read();
for(int x,y; q--; )
switch(read())
{
case 0: x=read(),y=read(),T.Split(x,y),printf("%d\n",T.sum[y]); break;
case 1: x=read(),y=read(),T.Link(x,y); break;
case 2: x=read(),y=read(),T.Cut(x,y); break;
case 3: T.Splay(x=read()),T.val[x]=read(); break;
} return 0;
}

洛谷.3690.[模板]Link Cut Tree(动态树)的更多相关文章

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

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

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

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

  3. Link Cut Tree 动态树 小结

    动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等 ...

  4. 洛谷P3690 Link Cut Tree (动态树)

    干脆整个LCT模板吧. 缺个链上修改和子树操作,链上修改的话join(u,v)然后把v splay到树根再打个标记就好. 至于子树操作...以后有空的话再学(咕咕咕警告) #include<bi ...

  5. LCT(link cut tree) 动态树

    模板参考:https://blog.csdn.net/saramanda/article/details/55253627 综合各位大大博客后整理的模板: #include<iostream&g ...

  6. 洛谷P2633 Count on a tree(主席树上树)

    题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...

  7. 模板Link Cut Tree (动态树)

    题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联 ...

  8. 洛谷 P2633 Count on a tree 主席树

    在一棵树上,我们要求点 $(u,v)$ 之间路径的第$k$大数. 对于点 $i$  ,建立 $i$  到根节点的一棵前缀主席树. 简单容斥后不难得出结果为$sumv[u]+sumv[v]−sumv[l ...

  9. 洛谷P2633 Count on a tree 主席树

    传送门:主席树 解题报告: 传送门! umm这题我还麻油开始做 所以 先瞎扯一波我的想法,如果错了我就当反面教材解释这种典型错误,对了我就不管了QwQ 就直接dfs,在dfs的过程中建树 然后就直接查 ...

随机推荐

  1. Word打开默认显示缩略图,而不是文档结构图

    So easy! 1.打开Word文档,点击缩略图右侧的"X",关闭缩略图: 2.打开菜单[视图],勾选"文档结构图": 3.关闭当前Word文档: 4.再次打 ...

  2. springboot系列十二、springboot集成RestTemplate及常见用法

    一.背景介绍 在微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端.我们可以使用JDK原生的URLConnection.Apache的Http Client.N ...

  3. windows系统上搭建redis集群哨兵及主从复制

    搭建master 修改redis配置redis.windows.conf: 修改监听端口:  port 26379 修改绑定IP: bind 127.0.0.1 添加redis日志:logfile & ...

  4. eclipse自动生成变量名声明(按方法返回值为本地变量赋值)

    eclipse自动生成变量名声明(按方法返回值为本地变量赋值) ctrl+2+L 这个快捷键可自动补全代码,极大提升编码效率! 注:ctrl和2同时按完以后释放,再快速按L.不能同时按! 比如写这句代 ...

  5. C/C++杂记:虚函数的实现的基本原理

    1. 概述 简单地说,每一个含有虚函数(无论是其本身的,还是继承而来的)的类都至少有一个与之对应的虚函数表,其中存放着该类所有的虚函数对应的函数指针.例: 其中: B的虚函数表中存放着B::foo和B ...

  6. zabbix系列(七)zabbix3.0添加对tcp连接数及状态的监控

    原理: netstat -an|awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}' TIME_WAIT 79 ESTABLISHED 6 LISTE ...

  7. C++ code:数值计算之矩形法求解积分问题

    积分的通常方法是将区域切割成一个个的小矩形,然后求这些小矩形的和.小矩形切割得越细,计算精度就越高,可以将切割小矩形的数量作为循环迭代变量,将前后两个不同精度下的小矩形和之差,作为逼近是否达到要求的比 ...

  8. cf220b

    不知道为什么线段树区间更新专题里有这题.. 可以用莫队解,也可以直接开数组解 /* n个询问,m个元素 O(m*m):记录每个元素出现次数,筛掉出现次数小于数值的数 */ #include<io ...

  9. JavaScrit全面总结

    前端技术的发展变化太快了,各种各样的框架.再变也离不开js.所以,在此把js的高级语法总结一遍.    js解析和执行包括:全局和函数 一:全局预处理 <script type="te ...

  10. webpack - require 概要

    webpack 是一个预编译模块打包工具,它只会对使用到的模块进行打包. 一个模块是否被使用?可以根据该模块是否被 require 来判断.如果require时指定的是具体的模块名称与正确的路径,那么 ...