zoukankan      html  css  js  c++  java
  • 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
    ",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;
    }
    
  • 相关阅读:
    记账本第二天
    记账本第一天
    HDU 1811
    Codeforces Round #246 (Div. 2) D. Prefixes and Suffixes
    KMP超强模板贴一份
    2014辽宁省赛总结
    Codeforces Round #244 (Div. 2)
    CodeForces 383D Antimatter
    NEU 1351 Goagain and xiaodao's romantic story I
    UVA 10692 Huge Mod
  • 原文地址:https://www.cnblogs.com/jklover/p/10388880.html
Copyright © 2011-2022 走看看