卧薪尝胆,厚积薄发。
星球联盟
Date: Thu Nov 22 09:21:04 CST 2018 In Category: NoCategory

Description:

如果两个星球在一个点双里,那么他们在一个联盟中,支持加边,询问这个联盟中星球数。
$1\leqslant n\leqslant 200000$

Solution:

$LCT$ 维护点双的套路,但是有了一些更深的理解,每次缩点时实际是把这个重链 $splay$ ,用并查集合到了一起,而前面那些 $splay$ 的操作都不用变是因为他们都是重链操作,但是这时虚边还没有操作,因此在 $access$ 的时候跳虚边就要用并查集跳。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cctype>
#include<cstring>
using namespace std;
int n,m,p;
#define MAXN 200010
struct node
{
int c[2],fa,siz,sum;
bool rev;
node(){sum = 0;}
}t[MAXN];
bool isroot(int k){return (t[t[k].fa].c[0] != k && t[t[k].fa].c[1] != k);}
void maintain(int k)
{
t[k].sum = t[k].siz;
if(t[k].c[0] != 0)t[k].sum += t[t[k].c[0]].sum;
if(t[k].c[1] != 0)t[k].sum += t[t[k].c[1]].sum;
return;
}
void connect(int k,int f,int p){t[k].fa = f;t[f].c[p] = k;return;}
int id(int k){return (t[t[k].fa].c[0] == k ? 0 : 1);}
void rotate(int x)
{
int y = t[x].fa,z = t[y].fa,fx = id(x),fy = id(y);
if(!isroot(y))t[z].c[fy] = x;
t[x].fa = z;
connect(t[x].c[fx ^ 1],y,fx);
connect(y,x,fx ^ 1);
maintain(y);maintain(x);
return;
}
void pushdown(int k)
{
if(t[k].rev)
{
t[t[k].c[0]].rev ^= 1;t[t[k].c[1]].rev ^= 1;
swap(t[k].c[0],t[k].c[1]);t[k].rev = false;
}
return;
}
stack<int> s;
void splay(int x)
{
s.push(x);
for(int i = x;!isroot(i);i = t[i].fa)s.push(t[i].fa);
while(!s.empty()){pushdown(s.top());s.pop();}
while(!isroot(x))
{
int y = t[x].fa;
if(isroot(y)){rotate(x);break;}
if(id(x) == id(y)){rotate(y);rotate(x);}
else{rotate(x);rotate(x);}
}
return;
}
int f[MAXN];
int find(int x){return (x == f[x] ? x : f[x] = find(f[x]));}
void access(int k)
{
for(int i = 0;k;i = k,k = t[i].fa = find(t[k].fa))
{
splay(k),t[k].c[1] = i;maintain(k);
}
return;
}
void makeroot(int k){access(k);splay(k);t[k].rev ^= 1;return;}
int findroot(int k)
{
access(k);splay(k);
while(t[k].c[0] != 0)k = t[k].c[0];
return k;
}
void remove(int rt,int k)
{
if(rt == 0)return;
f[rt] = k;t[k].siz += t[rt].siz;
remove(t[rt].c[0],k);
remove(t[rt].c[1],k);
return;
}
void link(int x,int y,int type)
{
x = find(x);y = find(y);
if(x == y)
{
if(type)printf("%d\n",t[x].siz);
return;
}
makeroot(x);
if(findroot(y) != x)
{
t[x].fa = y;
if(type)puts("No");
return;
}
access(y);splay(x);
remove(t[x].c[1],x);
if(type)printf("%d\n",t[x].siz);
return;
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i = 1;i <= n;++i)t[i].sum = t[i].siz = 1;
for(int i = 1;i <= n;++i)f[i] = i;
int a,b;
for(int i = 1;i <= m;++i)
{
scanf("%d%d",&a,&b);
link(a,b,0);
}
for(int i = 1;i <= p;++i)
{
scanf("%d%d",&a,&b);
link(a,b,1);
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡