洛谷.3690.[模板]Link Cut Tree(动态树)
#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(动态树)的更多相关文章
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- 洛谷P3690 [模板] Link Cut Tree [LCT]
题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...
- Link Cut Tree 动态树 小结
动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等 ...
- 洛谷P3690 Link Cut Tree (动态树)
干脆整个LCT模板吧. 缺个链上修改和子树操作,链上修改的话join(u,v)然后把v splay到树根再打个标记就好. 至于子树操作...以后有空的话再学(咕咕咕警告) #include<bi ...
- LCT(link cut tree) 动态树
模板参考:https://blog.csdn.net/saramanda/article/details/55253627 综合各位大大博客后整理的模板: #include<iostream&g ...
- 洛谷P2633 Count on a tree(主席树上树)
题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...
- 模板Link Cut Tree (动态树)
题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联 ...
- 洛谷 P2633 Count on a tree 主席树
在一棵树上,我们要求点 $(u,v)$ 之间路径的第$k$大数. 对于点 $i$ ,建立 $i$ 到根节点的一棵前缀主席树. 简单容斥后不难得出结果为$sumv[u]+sumv[v]−sumv[l ...
- 洛谷P2633 Count on a tree 主席树
传送门:主席树 解题报告: 传送门! umm这题我还麻油开始做 所以 先瞎扯一波我的想法,如果错了我就当反面教材解释这种典型错误,对了我就不管了QwQ 就直接dfs,在dfs的过程中建树 然后就直接查 ...
随机推荐
- python 历险记(二)— python 的面向对象
目录 前言 类和对象 如何定义和实例化类? 如何定义和使用属性? 什么是方法? 静态方法和普通方法 构造函数该怎么写? str 方法怎么写? 多态是什么? 继承性和 java 是一样的吗? 父类和子类 ...
- Python中__repr__和__str__区别
Python中__repr__和__str__区别 看下面的例子就明白了 class Test(object): def __init__(self, value='hello, world!'): ...
- 自助Linux之问题诊断工具strace【转】
转自:http://www.cnblogs.com/bangerlee/archive/2012/02/20/2356818.html 引言 “Oops,系统挂死了..." “Oops,程序 ...
- 如何在linux下检测内存泄漏(转)
本文转自:http://www.ibm.com/developerworks/cn/linux/l-mleak/ 本文针对 linux 下的 C++ 程序的内存泄漏的检测方法及其实现进行探讨.其中包括 ...
- 四种加载React数据的技术对比(Meteor 转)
1.四种加载React数据的技术对比(Meteor 转) : https://sanwen8.cn/p/31e4kdE.html 2. Meteor + Appolo TelescopeJS/Te ...
- cocos2d-x播放视频的处理
cocos2d-x是支持直接播放视频的,用的是Native端的播放器,视频的默认层级是在cocos的层级之上,如果是想让视频上面有cocos的控件,只能将视频的UI层级放在最下面,这个方法网上已经有比 ...
- 用命令打开本地tomcat服务器
1.点击开始菜单,搜索cmd,默认第一个结果是cmd.exe, 鼠标右键用管理员权限打开(win7及以上版本系统) 启动命令是net start tomcat8 (我电脑是tomcat8,如果是tom ...
- vue及webpack在项目中的一些优化
传送:https://www.haorooms.com/post/vue_webpack_youhua
- ORACLE与SQLSERVER数据转换
前言: 将SQLServer数据库中的表和数据全量导入到Oracle数据库,通过Microsoft SqlServer Management Studio工具,直接导入到oracle数据库,免去了生成 ...
- cf803c 数论
细节很多的题 #include<bits/stdc++.h> using namespace std; #define ll long long int main(){ ll n,k,tm ...