Chino with Rewrite

在这里插入图片描述


看到值最大为60,我们可以想到状态压缩,把60个值全部压成二进制。每次动态连接,求链上或的和。

当然我们可以离线去树剖,用线段树维护。

但是对于会LCT的人,当然我们要用LCT啦,直接LCT维护链上或的和就好了。

AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
const int N=1e5+10;
int cnt,st[N],n,q;
struct node{
	int ch[2],fa,re,val,col;
}t[N];
inline void push_up(int p){
	t[p].val=t[ls(p)].val|t[rs(p)].val|(1LL<<t[p].col);
}
inline void push_re(int p){swap(ls(p),rs(p)); t[p].re^=1;}
inline void push_down(int p){
	if(!t[p].re)	return;
	if(ls(p))	push_re(ls(p));	if(rs(p))	push_re(rs(p)); t[p].re^=1;
}
inline bool isroot(int x){return ls(t[x].fa)!=x&&rs(t[x].fa)!=x;}
inline void rotate(int x){
	int y=t[x].fa,z=t[y].fa,k=rs(y)==x,w=t[x].ch[!k];
	if(!isroot(y))	t[z].ch[rs(z)==y]=x; t[x].ch[!k]=y; t[y].ch[k]=w;
	if(w)	t[w].fa=y; t[y].fa=x; t[x].fa=z;	push_up(y);
}
inline void splay(int x){
	cnt=1;	st[cnt]=x; int y=x;
	while(!isroot(y))	st[++cnt]=y=t[y].fa;
	while(cnt)	push_down(st[cnt--]);
	while(!isroot(x)){
		int y=t[x].fa,z=t[y].fa;
		if(!isroot(y))	rotate((ls(y)==x)^(ls(z)==y)?x:y); rotate(x);
	}push_up(x);
}
inline void access(int x){
	for(int y=0;x;x=t[y=x].fa) splay(x),rs(x)=y,push_up(x); 
}
inline void makeroot(int x){
	access(x); splay(x); push_re(x);
}
inline int find(int x){
	access(x); splay(x); while(ls(x)) push_down(x),x=ls(x); 
	splay(x);	return x;
}
inline void split(int x,int y){
	makeroot(x); access(y); splay(y);
}
inline void link(int x,int y){
	if(find(x)==find(y))	return ;
	int tc=t[x].col+t[y].col>>1;
	makeroot(x),t[x].fa=y,t[x].col=tc,makeroot(y),t[y].col=tc;
}
inline void cut(int x,int y){
	makeroot(x); 
	if(find(y)==x&&t[y].fa==x&&!ls(y)) t[y].fa=rs(x)=0,push_up(x);
}
inline int ask(int x,int y){
	if(find(x)!=find(y))	return -1;
	split(x,y);	int tc=t[y].val,res=0;
	for(;tc;tc-=tc&(-tc))	res++;
	return res;
}
signed main(){
	cin>>n>>q;
	for(int i=1;i<=n;i++)	cin>>t[i].col;
	for(int i=1,op,x,y;i<=q;i++){
		scanf("%lld %lld %lld",&op,&x,&y);
		if(op==1)	link(x,y);
		else	printf("%lld\n",ask(x,y));
	}
	return 0;
}
发布了416 篇原创文章 · 获赞 228 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/103923632