uoj#207. 共價大爺遊長沙

miaom又來做LCT了!//lych:無敵

由於不是很懂LCT子樹信息維護的那套理論,想了好久(搞得樹剖的子樹維護就會了一樣!)。

首先是一個很巧妙的轉化——將邊在鏈上轉化爲這條邊能將鏈的頂點分開。給每組頂賦一個隨機權,每次可以把邊斷掉,查詢每個聯通塊內權值異或和是否等於所有頂點權值異或和,就是子樹異或和。

然後發現動態樹上子樹不是dfs序連續那麼簡單,他應該是(當前點及沿偏愛邊往下走得到的點)以及他們的虛邊的子樹。然後維護一些值(splay 區間虛兒子&自己和
      單點&虛兒子和)。

LCT的代碼來自@lbn187板子的默寫,如有錯誤不負責。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#define N 300005
using namespace std;
int id,n,m,x,y,p,qx[N],qy[N],now,val[N],ly;
int c[N][2],fa[N],v[N],s[N],rev[N];
//子樹權值異或和
//splay 區間虛兒子&自己和 s
//單點&虛兒子和 v
//單點修改
bool RT(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
void rever(int x){rev[x]^=1;swap(c[x][0],c[x][1]);}
void up(int x)
{
	s[x]=s[c[x][0]]^s[c[x][1]]^v[x];
}
void dn(int x)
{
	if (rev[x])
		rev[x]=0,rever(c[x][0]),rever(c[x][1]);
}
void pd(int x){if (!RT(x)) pd(fa[x]);dn(x);}
void rot(int x)
{
	int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
	if (!RT(y)) c[z][c[z][1]==y]=x;
	fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
	c[y][l]=c[x][r];c[x][r]=y;up(y);up(x);
}
void splay(int x,int y=0)
{
	for (pd(x);!RT(x);rot(x))
		if (!RT(y=fa[x]))
			rot(c[y][0]==x^c[fa[y]][0]==y?x:y);
}
void acc(int x)
{
	for (int y=0;x;y=x,x=fa[x])
		splay(x),v[x]^=s[c[x][1]]^s[y],c[x][1]=y,up(x);
}
void MRt(int x){acc(x);splay(x);rever(x);}
void link(int x,int y){MRt(x);MRt(y);v[y]^=s[x];s[y]^=s[x];fa[x]=y;}
void cut(int x,int y){MRt(x);acc(y);splay(y);c[y][0]=fa[x]=0;up(y);}
void mdy(int x,int y){MRt(x);v[x]^=y;s[x]^=y;}
int qry(int x,int y){MRt(x);acc(y);return v[y]+s[c[y][1]];}
int main()
{
	int id;
	scanf("%d",&id);
	scanf("%d%d",&n,&m);
	for (int i=2;i<=n;i++)
		scanf("%d%d",&x,&y),link(x,y);
	for (int i=1;i<=m;i++)
	{
		scanf("%d",&p);
		if (p==1)
		{
			scanf("%d%d",&x,&y);
			cut(x,y);
			scanf("%d%d",&x,&y);
			link(x,y);
		}
		else if (p==2)
		{
			scanf("%d%d",&x,&y);
			val[++ly]=(rand()<<16)^rand();
			qx[ly]=x;qy[ly]=y;
			now^=val[ly];
			mdy(x,val[ly]);
			mdy(y,val[ly]);
		}
		else if (p==3)
		{
			scanf("%d",&x);
			now^=val[x];
			mdy(qx[x],val[x]);
			mdy(qy[x],val[x]);
		}
		else if (p==4)
		{
			scanf("%d%d",&x,&y);
			puts(qry(x,y)==now?"YES":"NO");
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章