警告 本篇文章作者已神志不清 文章内可能出现 病句 逻辑不通 粗口 爆鲤 瑟琴 低幼 第三类接触 外语 等特征 请阅读时注意过滤和脑补
妈蛋从下午五点开始写写到快九点才AC。。。。啊啊啊啊啊啊啊 啊啊啊啊啊啊啊 啊啊啊啊 啊啊啊啊啊啊啊 啊啊啊啊啊 啊啊啊啊 啊啊
题目大意:给定一堆点,提供三种操作:
1.给定x和y,询问x和y是否在一棵子树上
2.在x和y之间连一条边 数据保证x和y不连通
3.删除x和y之间的边 数据保证x和y之间有连边
乍一看这好像是并查集?但是并查集不支持拆分操作
仔细一看数据是森林 于是这题LCT
本来以为把2002的代码改改就能过 结果 NMB NMB NMB 啊啊啊啊啊啊啊啊 22323232323233333333333333333
该拆的边拆不掉 连边成了环 無限TLE
问题就在于这题是无根树
无根树Link的时候不能直接把节点和爸爸拆了 而是要把节点变成整棵树的根 然后再合并
而变为根节点的方式就是先Access+Splay 然后将x所在Splay子树反转 Splay在维护的时候要向上找到标记向下下传
Cut的时候先把x Access+Splay+反转 然后把x和右节点切断 把y Access 再切断一遍 把y Splay 这样一定保证y->fa==x && x->rs!=y
贴代码 下午没吃饭 饿死我了0.0
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 10100
using namespace std;
int n,m;
struct abcd{
abcd *ls,*rs,*fa;
bool mark;
abcd();
};
abcd *null=new abcd,tree[M];
abcd :: abcd()
{
ls=rs=fa=null;
}
void Zig(abcd*x)
{
abcd*y=x->fa;
abcd*z=y->fa;
y->ls=x->rs;
x->rs->fa=y;
x->rs=y;
y->fa=x;
if (z->ls==y)
z->ls=x;
else if(z->rs==y)
z->rs=x;
x->fa=z;
}
void Zag(abcd*x)
{
abcd*y=x->fa;
abcd*z=y->fa;
y->rs=x->ls;
x->ls->fa=y;
x->ls=y;
y->fa=x;
if (z->ls==y)
z->ls=x;
else if(z->rs==y)
z->rs=x;
x->fa=z;
}
void Reverse(abcd *x)
{
if(x==x->fa->ls||x==x->fa->rs)
Reverse(x->fa);
if(x->mark)
{
swap(x->ls,x->rs);
x->mark=0;
x->ls->mark^=1;
x->rs->mark^=1;
}
}
void Splay(abcd*x)
{
abcd *y,*z;
Reverse(x);
for (;x->fa->ls==x||x->fa->rs==x;)
{
y=x->fa,z=y->fa;
if (y->ls==x)
{
if (z->ls==y)
Zig(y);
Zig(x);
}
else
{
if (z->rs==y)
Zag(y);
Zag(x);
}
}
}
void Access(abcd *x)
{
abcd *y=null;
while(x!=null)
{
Splay(x);
x->rs=y;
y=x;
x=x->fa;
}
}
void Query(abcd *x,abcd *y)
{
Access(x);
Splay(x);
while(y->fa!=null)
y=y->fa;
if(y==x)
puts("Yes");
else
puts("No");
}
void Link(abcd *x,abcd *y)
{
Access(x);
Splay(x);
x->mark^=1;
Reverse(x);
x->ls=null;
x->fa=y;
}
void Cut(abcd *x,abcd *y)
{
Access(x);
Splay(x);
x->mark^=1;
Reverse(x);
x->rs=null;
Access(y);
x->rs=null;
Splay(y);
y->fa=null;
}
int main()
{
null->ls=null->rs=null->fa=null;
int i,x,y;
char p[100];
cin>>n>>m;
for (i=1;i<=m;i++)
{
scanf("%s%d%d",p,&x,&y);
if(p[0]=='Q')
Query(&tree[x],&tree[y]);
else if(p[0]=='C')
Link(&tree[x],&tree[y]);
else
Cut(&tree[x],&tree[y]);
}
}