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

不知道为什么RE

#include<bits/stdc++.h>
#define MAXN 1000005
typedef long long ll;

using namespace std;

ll n,m,tot,q[MAXN * 2];

struct node{
	ll ch[2],f,res,val,sum;
}t[MAXN];

ll pp(ll rt){swap(t[rt].ch[0] , t[rt].ch[1]);t[rt].res = (t[rt].res ^ 1);}
ll push_down(ll rt){if(!t[rt].res)return 0;pp(t[rt].ch[0]) , pp(t[rt].ch[1]);t[rt].res = 0;}
ll up(ll rt){t[rt].sum = (t[t[rt].ch[0]].sum ^ t[t[rt].ch[1]].sum ^ t[rt].val);}
ll get(ll rt){return (t[t[rt].f].ch[1] == rt);}
ll checkrt(ll rt){return (t[rt].f && (t[t[rt].f].ch[0] == rt || t[t[rt].f].ch[1] == rt));}

int rote(ll rt){
	ll ff = t[rt].f , gg = t[ff].f , d = get(rt) , cc = t[rt].ch[d ^ 1];
	if(checkrt(ff))t[gg].ch[get(ff)] = rt;
	t[ff].f = rt , t[rt].ch[d ^ 1] = ff , t[rt].f = gg , t[cc].f = ff , t[ff].ch[d] = cc;
	up(ff) , up(rt) , up(gg);	
}

int splay(ll rt){
	ll x = rt , zz = 0;
	q[++zz] = x;
	while(checkrt(x))x = t[x].f , q[++zz] = x;
	while(zz){
		push_down(q[zz]);
		zz--;
	}
	for(ll ff = t[rt].f ; checkrt(rt) ; rote(rt)){
		if(checkrt(ff = t[rt].f)){
			if(get(ff) == get(rt))rote(ff);
			else rote(rt);
		}
	}	
	up(rt);
}

ll access(ll rt){for(ll y = 0 ; rt ; rt = t[y = rt].f)splay(rt) ,t[rt].ch[1] = y;}

ll makert(ll rt){
	access(rt);
	splay(rt);
	pp(rt);
}

ll foundrt(ll x){
	access(x);
	splay(x);
	while(t[x].ch[0])x = t[x].ch[0];
	splay(x);
	return x;
	
}

ll split(ll x , ll y){
	makert(x);
	access(y);
	splay(y);
}

ll link(ll x , ll y){
	if(foundrt(x) == foundrt(y))return 0;
	makert(x);
	t[x].f = y;
}

ll cut(ll x , ll y){
	makert(x);
	if(foundrt(x) != foundrt(y) || t[y].f != x || (t[x].ch[get(y)] != y))return 0;
	t[x].ch[get(y)] = 0;
	t[y].f = 0;
}

int main(){
	cin>>n>>m;
	ll tp,x,y;
	for(int i = 1 ; i <= n ; i++){
		scanf("%lld" , &x);tot++;
		t[tot].val = x;
	}
	for(ll i = 1 ; i <= m ; i++){
		scanf("%lld%lld%lld" , &tp , &x , &y);
		if(tp == 0){
			split(x , y);
			cout<<t[y].sum<<endl;
		}
		if(tp == 1)link(x , y);
		if(tp == 2)cut(x , y);	
		if(tp == 3){
			makert(x);
			t[x].val = y;
			up(x); 
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值