[P3690]Link Cut Tree

Description:

给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。

0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。

1:后接两个整数(x,y),代表连接x到y,若x到y已经联通则无需连接。

2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。

3:后接两个整数(x,y),代表将点x上的权值变成y。

模板,不解释,详见代码

#include<bits/stdc++.h>
using namespace std;
const int mxn=3e5+5;
int n,m,t[mxn],fa[mxn],st[mxn],rev[mxn],val[mxn],ch[mxn][2];

namespace lct {
    int isnotrt(int x) {
        return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
    };
    void push_up(int x) {
        t[x]=t[ch[x][0]]^t[ch[x][1]]^val[x];
    };
    void push_down(int x) {
        if(rev[x]) {
            rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
            swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
            swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
            rev[x]=0;
        }
    }
    void rotate(int x) {
        int y=fa[x],z=fa[y],tp=ch[y][1]==x;
        if(isnotrt(y)) ch[z][ch[z][1]==y]=x;/**/ fa[x]=z;
        ch[y][tp]=ch[x][tp^1],fa[ch[x][tp^1]]=y;
        ch[x][tp^1]=y,fa[y]=x;
        push_up(y),push_up(x);
    };
    void splay(int x) {
        int tp=x,s=0; st[++s]=tp;
        while(isnotrt(tp)) st[++s]=tp=fa[tp];
        while(s) push_down(st[s--]);
        while(isnotrt(x)) {
            int y=fa[x],z=fa[y];
            if(isnotrt(y))
                (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
    };
    void access(int x) {
        for(int y=0;x;x=fa[y=x])
            splay(x),ch[x][1]=y,push_up(x);
    };
    void makert(int x) {
        access(x); splay(x);
        swap(ch[x][0],ch[x][1]);
        rev[x]^=1;
    };
    int findrt(int x) {
        access(x); splay(x);
        while(ch[x][0]) push_down(x),x=ch[x][0];
        splay(x); return x;
    };
    void split(int x,int y) {
        makert(x); access(y); splay(y);
    };
    void link(int x,int y) {
        makert(x);
        if(findrt(y)!=x) fa[x]=y;
    };
    void cut(int x,int y) {
        makert(x);
        if(findrt(y)==x/**/&&fa[y]==x&&!ch[y][0]) {
            fa[y]=ch[x][1]=0;
            push_up(x);
        }
    };
}
using namespace lct;

int main()
{
    scanf("%d%d",&n,&m); int opt,x,y;
    for(int i=1;i<=n;++i) scanf("%d",val+i);
    while(m--) {
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==0) split(x,y),printf("%d\n",t[y]);
        else if(opt==1) link(x,y);
        else if(opt==2) cut(x,y);
        else splay(x),val[x]=y;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/list1/p/10375845.html

时间: 2024-07-31 10:38:15

[P3690]Link Cut Tree的相关文章

P3690 Link Cut Tree (动态树)

干脆整个LCT模板吧. 缺个链上修改和子树操作,链上修改的话join(u,v)然后把v splay到树根再打个标记就好. 至于子树操作...以后有空的话再学(咕咕咕警告) 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10; 5 int n,m,a[N],Xor[N],fa[N],ch[N][2],flp[N],sta[N],tp; 6 #define l(u

P3690 【模板】Link Cut Tree (动态树)

P3690 [模板]Link Cut Tree (动态树) https://www.luogu.org/problemnew/show/P3690 分析: LCT模板 代码: 注意一下cut! 1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 const int N = 300100; 7 8 int val[N],fa[N],ch[N][2],rev[N],sum[N],st[N],top;

AC日记——【模板】Link Cut Tree 洛谷 P3690

[模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 300005 int n,m,val[maxn]; int top,ch[maxn][2],f[maxn],xr[maxn],q[maxn],rev[maxn]; inline void in(int &now) { int if_z=1;now=0; char Cget=getchar(); while

LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到y已经联通则无需连接. 2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在. 3:后接两个整数(x,y),代表将点x上的权值变成y. 输入输出

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

A. Link/Cut Tree Programmer Rostislav got seriously interested in the Link/Cut Tree data structure, which is based on Splay trees. Specifically, he is now studying the expose procedure. Unfortunately, Rostislav is unable to understand the definition

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

link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isroot(int x):判断x是否为所在重链(splay)的根 void down(int x):下放各种标记 void rotate(int x):在x所在重链(splay)中将x旋转到fa[x]的位置上 void splay(int x):在x坐在重链(splay)中将x旋转到根 void acce

脑洞大开加偏执人格——可持久化treap版的Link Cut Tree

一直没有点动态树这个科技树,因为听说只能用Splay,用Treap的话多一个log.有一天脑洞大开,想到也许Treap也能从底向上Split.仔细思考了一下,发现翻转标记不好写,再仔细思考了一下,发现还是可以写的,只需要实时交换答案二元组里的两棵树,最后在吧提出来的访问节点放回去就行了.本着只学一种平衡树的想法,脑洞大开加偏执人格的开始写可持久化Treap版的Link Cut Tree... 写了才发现,常数硕大啊!!!代码超长啊!!!因为merge是从上到下,split从下到上,pushdow

link cut tree 入门

鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,

HDOJ 题目3966 Aragorn&#39;s Story(Link Cut Tree成段加减点权,查询点权)

Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5505    Accepted Submission(s): 1441 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lor