LCT

我觉得这种东西就是工程题,好像这就是Splay的唯一用途吧

神仙的博客

#include<bits/stdc++.h>
#define lc(p) c[p][0]
#define rc(p) c[p][1]
using namespace std;
const int N=310000;
int f[N],c[N][2],v[N],s[N],st[N];
int t[N],n,m;
int nroot(int p){return lc(f[p])==p||rc(f[p])==p;}
void up(int x)
{
	s[x]=s[lc(x)]^s[rc(x)]^v[x];
	return;
}
void down(int x)
{
	if(t[x])
	{
		swap(lc(x),rc(x));
		t[x]=0; t[lc(x)]^=1,t[rc(x)]^=1;
	}
	return;
}
void rotate(int x)
{
	int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
	if(nroot(y)) c[z][c[z][1]==y]=x;
	c[x][!k]=y,c[y][k]=w;
	if(w) f[w]=y;
	f[y]=x,f[x]=z;
	up(y);
}
void splay(int x)
{
	int y=x,z=0;
	st[++z]=y;
	while(nroot(y)) st[++z]=y=f[y];
	while(z>0) down(st[z--]);
	while(nroot(x))
	{
		y=f[x],z=f[y];
		if(nroot(y)) rotate((c[y][1]==x)^(c[z][1]==y)?x:y);
		rotate(x);
	}
	up(x);
	return;
}
void access(int x)
{
	for(int y=0;x;x=f[y=x]) splay(x),rc(x)=y,up(x);
	return;
}
void makeroot(int x)
{
	access(x),splay(x);
	t[x]^=1;
	return;
}
int findroot(int x)
{
	access(x),splay(x);
	while(lc(x)) down(x),x=lc(x);
	splay(x);
	return x;
}
void split(int x,int y)
{
	makeroot(x);
	access(y),splay(y);
	return;
}
void link(int x,int y)
{
	makeroot(x);
	if(findroot(y)!=x) f[x]=y;
	return;
}
void cut(int x,int y)
{
	makeroot(x);
	if(findroot(y)==x&&f[y]==x&&lc(y)==0) 
	{
		f[y]=rc(x)=0;
		up(x);
	}
	return;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&v[i]);
	int op,x,y;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&op,&x,&y);
		if(op==0) split(x,y),printf("%d
",s[y]);
		else if(op==1) link(x,y);
		else if(op==2) cut(x,y);
		else splay(x),v[x]=y;
	}
	return 0;
}

题目

Tree II

#include<bits/stdc++.h>
#define lc(p) c[p][0]
#define rc(p) c[p][1]
using namespace std;
const int N=110000;
const int mod=51061;
int a[N],b[N],t[N];
int c[N][2],f[N],s[N],v[N],siz[N],st[N];
int n,q;
int nroot(int x){return lc(f[x])==x||rc(f[x])==x;}
void up(int x)
{
	s[x]=((s[lc(x)]+s[rc(x)])%mod+v[x])%mod;
	siz[x]=siz[lc(x)]+siz[rc(x)]+1;
	return;
}
void D2(int x,int B)
{
	v[x]=(v[x]+B)%mod;
	s[x]=(s[x]+1ll*siz[x]*B%mod)%mod;
	b[x]=(b[x]+B)%mod;
	return;
}
void D1(int x,int A)
{
	v[x]=1ll*v[x]*A%mod;
	s[x]=1ll*s[x]*A%mod;
	a[x]=1ll*a[x]*A%mod;
	b[x]=1ll*b[x]*A%mod;
	return;
}
void D3(int x)
{
	t[x]^=1;
	return;
}
void down(int x)
{
	if(a[x]!=1)
	{
		if(lc(x)) D1(lc(x),a[x]);
		if(rc(x)) D1(rc(x),a[x]);
		a[x]=1;
	}
	if(b[x])
	{
		if(lc(x)) D2(lc(x),b[x]);
		if(rc(x)) D2(rc(x),b[x]);
		b[x]=0;
	}
	if(t[x])
	{
		swap(lc(x),rc(x));
		if(lc(x)) D3(lc(x));
		if(rc(x)) D3(rc(x));
		t[x]=0;
	}
	return;
}
void rotate(int x)
{
	int y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
	if(nroot(y)) c[z][c[z][1]==y]=x;
	c[x][!k]=y,c[y][k]=w;
	if(w) f[w]=y;
	f[y]=x,f[x]=z;
	up(y);
	return;
}
void splay(int x)
{
	int y=x,z=0;
	st[++z]=y;
	while(nroot(y)) st[++z]=y=f[y];
	while(z>0) down(st[z--]);
	while(nroot(x))
	{
		y=f[x],z=f[y];
		if(nroot(y)) rotate((c[y][1]==x)^(c[z][1]==y)?x:y);
		rotate(x);
	}
	up(x);
	return;
}
void access(int x)
{
	for(int y=0;x;x=f[y=x]) splay(x),rc(x)=y,up(x);
	return;
}
void makeroot(int x)
{
	access(x);
	splay(x);
	t[x]^=1;
	return;
}
int findroot(int x)
{
	access(x),splay(x);
	while(lc(x)) down(x),x=lc(x);
	splay(x);
	return x;
}
void split(int x,int y)
{
	makeroot(x);
	access(y);
	splay(y);
	return;
}
void link(int x,int y)
{
	makeroot(x),f[x]=y;
	return;
}
void cut(int x,int y)
{
	split(x,y);
	lc(y)=f[x]=0;	
	up(y);
	return;
}
void out()
{
	for(int j=1;j<=n;j++) cout<<s[j]<<" "<<v[j]<<" "<<lc(j)<<" "<<rc(j)<<" "<<f[j]<<" "<<siz[j]<<" "<<a[j]<<" "<<b[j]<<endl;
	return;
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) v[i]=1,siz[i]=1,s[i]=1,a[i]=1,t[i]=lc(i)=rc(i)=0;
	int u,v;
	for(int i=1;i<=n-1;i++)
	{
		scanf("%d%d",&u,&v);
		link(u,v);
	}
	int ou,ov,c;
	char op[5];
	for(int i=1;i<=q;i++)
	{
		scanf("%s",op);
		if(op[0]=='+')
		{
			scanf("%d%d%d",&u,&v,&c);
			split(u,v);
			D2(v,c);
		}
		else if(op[0]=='-')
		{
			scanf("%d%d%d%d",&u,&v,&ou,&ov);
			cut(u,v);
			link(ou,ov);
		}
		else if(op[0]=='*')
		{
			scanf("%d%d%d",&u,&v,&c);
			split(u,v);
			D1(v,c);
		}
		else
		{
			scanf("%d%d",&u,&v);
			split(u,v);
			printf("%d
",s[v]);
		}
	}
	return 0;
} 
  • 数据结构还是要自己理解啊

维护虚子树

#include<bits/stdc++.h>
#define broken cerr << __FUNCTION__ <<" " << __LINE__ << endl
#define lc(x) ch[x][0]
#define rc(x) ch[x][1]
using namespace std;
typedef unsigned long long ul;
const int N = 1e5 + 10, M = 3e5 + 10;
int id, n, m;
int l[M], r[M], tot = 0;
int ch[N][2], fa[N], rev[N], st[N], top = 0;
ul v[N], s[N], key[M], sv[N], all = 0;
ul brd() {
  ul x = rand();
  x = (x << 16) | rand();
  x = (x << 16) | rand(); x = (x << 16) | rand();
  x ^= x << 31;
  x ^= x >> 18;
  x ^= x << 7;
  return x ^ 20051047;
}
int nrt(int x) {
  return lc(fa[x]) == x || rc(fa[x]) == x;
}

void upd(int x) {
  s[x] = s[lc(x)] ^ s[rc(x)] ^ v[x] ^ sv[x];
  return;
}

void pushd(int x) {
  if(!rev[x]) return;
  swap(lc(x), rc(x));
  rev[x] = 0, rev[lc(x)] ^= 1, rev[rc(x)] ^= 1;
  return;
}


void rotate(int x) {
  int y = fa[x], z = fa[y];
  int p = (ch[y][1] == x), k = ch[x][!p];
  if(nrt(y)) ch[z][ch[z][1] == y] = x;
  ch[x][!p] = y, ch[y][p] = k, fa[y] = x, fa[x] = z;
  if(k) fa[k] = y;
  return upd(y), void();
}

void splay(int x) {
  int y = x;
  top = 0;
  st[++top] = x;
  while(nrt(y)) st[++top] = y = fa[y];
  while(top > 0) pushd(st[top--]);
  while(nrt(x)) {
    int y = fa[x], z = fa[y];
    if(nrt(y)) rotate((ch[y][1] == x) ^ (ch[z][1] == y) ? x : y);
    rotate(x);
  }
  return upd(x), void();
}

void access(int x) {
  for(int y = 0; x; x = fa[y = x]) {
    splay(x);
    sv[x] ^= s[y] ^ s[rc(x)];
    rc(x) = y;
    upd(x);
  }
  return;
}


void makeroot(int x) {
  access(x), splay(x), rev[x] ^= 1;
  return;
}

void split(int x, int y) {
  makeroot(x), access(y), splay(y);
  return;
}

void link(int x, int y) {
  split(x, y), fa[x] = y, sv[y] ^= s[x];
  upd(y);
}

void cut(int x, int y) {
  split(x, y), fa[x] = 0, ch[y][0] = 0;
  upd(y);
}

void initnode(int n) {
  for(int i = 1; i <= n; i++) rev[i] = lc(i) = rc(i) = s[i] = sv[i] = v[i] = 0;
  return;
}

void modify(int x, ul y) {
  access(x), splay(x), v[x] ^= y, upd(x);
  return;
}

void put() {
  for(int i = 1; i <= n; i++) {
    cout << i <<" " << fa[i] <<" " << lc(i) <<" " << rc(i) << endl;
  }
}

ul quer(int x, int y) {
  cut(x, y);
  makeroot(y);
  ul sum = s[y];
  link(x, y);
  return sum == all;
}

int main() {
  srand(time(NULL));
  scanf("%d", &id);
  scanf("%d%d", &n, &m);
  initnode(n);
  for(int i = 1; i <= n - 1; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    link(u, v);
  }
  for(int amo = 1; amo <= m; amo++) {
    int opt, x, y, u, v;
    scanf("%d", &opt);
    if(opt == 1) {
      scanf("%d%d%d%d", &x, &y, &u, &v);
      cut(x, y), link(u, v);
    } else if(opt == 2) {
      scanf("%d%d", &x, &y);
      ul V = brd();
      modify(x, V), modify(y, V);
      l[++tot] = x, r[tot] = y, key[tot] = V, all ^= V;
    } else if(opt == 3) {
      scanf("%d", &x);
      modify(l[x], key[x]), modify(r[x], key[x]), all ^= key[x];
    } else {
      scanf("%d%d", &x, &y);
      printf(quer(x, y) ? "YES
" : "NO
");
    }
  }
  return 0;
}
原文地址:https://www.cnblogs.com/SegmentTree/p/13050352.html