题意
一棵LCT,支持link,cut操作。在线问两个点的连通性。
题解
LCT初学题。
注意两个地方。
splay树维护的是LCT的信息。莫将splay看成被维护信息的树。
如何link和cut?
link很简单。
void link(int x,int y){
mroot(x);
tr[x].f=y;
}
但是本人对cut操作一直有个困惑。
就是LCT中没有这条边怎么办?
需要特判。
详见我的博客:LCT学习之旅
reverse标记记得实时传。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10010
#define M 200010
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
struct note{
int x,y,u,v,op;
}qu[M];
struct lct{
int f,c[2],rev;
}tr[N];
int i,j,k,l,n,m;
int cnt,gs,tot,a[M*2],b[M*2];
char ch;
int Swap(int &x,int &y){x=x^y;y=x^y;x=x^y;}
void init(){
int i;
scanf("%d%d",&n,&m);
fo(i,1,m){
ch=getchar();
while((ch^'C')&&(ch^'D')&&(ch^'Q'))ch=getchar();
if(ch=='C'){
ch=getchar();
while(ch>='a'&&ch<='z')ch=getchar();
scanf("%d%d",&qu[i].x,&qu[i].y);
a[++tot]=qu[i].x;a[++tot]=qu[i].y;
qu[i].op=0;
}else
if(ch=='D'){
ch=getchar();
while(ch>='a'&&ch<='z')ch=getchar();
scanf("%d%d",&qu[i].x,&qu[i].y);
a[++tot]=qu[i].x;a[++tot]=qu[i].y;
qu[i].op=1;
}else{
ch=getchar();
while(ch>='a'&&ch<='z')ch=getchar();
scanf("%d%d",&qu[i].x,&qu[i].y);
a[++tot]=qu[i].x;a[++tot]=qu[i].y;
qu[i].op=2;
}
}
}
void lsh(){
int i;
fo(i,1,tot)b[i]=a[i];
sort(b+1,b+tot+1);
cnt=unique(b+1,b+tot+1)-b-1;
fo(i,1,m){
qu[i].u=lower_bound(b+1,b+cnt+1,qu[i].x)-b;
qu[i].v=lower_bound(b+1,b+cnt+1,qu[i].y)-b;
}
}
bool isroot(int x){
return (tr[tr[x].f].c[0]^x)&&(tr[tr[x].f].c[1]^x);
}
int dir(int x){return tr[tr[x].f].c[1]==x;}
void pushrev(int x){
if(!x)return;
Swap(tr[x].c[0],tr[x].c[1]);
tr[x].rev^=1;
}
void pdw(int x){
if(tr[x].rev){
pushrev(tr[x].c[0]);
pushrev(tr[x].c[1]);
tr[x].rev=0;
}
}
void rotate(int x){
int y=tr[x].f,z=dir(x);
pdw(y);pdw(x);
if(!isroot(y))tr[tr[y].f].c[dir(y)]=x;
tr[y].c[z]=tr[x].c[z^1];
tr[x].f=tr[y].f;
tr[y].f=x;
tr[tr[x].c[z^1]].f=y;tr[x].c[z^1]=y;
}
void splay(int x){
int i,y,z;
while(!isroot(x)){
y=tr[x].f;
if(!isroot(y)){
rotate(dir(x)^dir(y)?x:y);
}
rotate(x);
}
}
void access(int x){
int i,y=0;
while(x){
splay(x);
pdw(x);
tr[x].c[1]=y;
y=x;
x=tr[x].f;
}
}
void mroot(int x){
access(x);
splay(x);
pushrev(x);
}
int groot(int x){
int w=x;
access(x);
pdw(x);
splay(x);
while(tr[w].c[0]){
w=tr[w].c[0];
}
return w;
}
void link(int x,int y){
mroot(x);
tr[x].f=y;
}
bool judge(int x,int y){
if(!tr[x].c[0])return 0;
x=tr[x].c[0];
while(tr[x].c[1]){
x=tr[x].c[1];
}
return x==y;
}
void cut(int x,int y){
mroot(x);
pdw(x);
access(y);
splay(y);
pdw(x);
if(judge(y,x)){
tr[tr[y].c[0]].f=0;
tr[y].c[0]=0;
}
}
void Operate(){
int i;
fo(i,1,m){
if(qu[i].op==0){
link(qu[i].u,qu[i].v);
}else
if(qu[i].op==1){
cut(qu[i].u,qu[i].v);
}else{
if(groot(qu[i].u)==groot(qu[i].v))
printf("Yes\n");
else printf("No\n");
}
}
}
int main(){
init();
lsh();
Operate();
return 0;
}