lct
这题给我的感觉就是:指针真nm难调
第一次写真蛋疼
码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 500000
using namespace std;
int n,m,x,y;
char ss[99];
struct tree
{
tree *ch[2],*fu;
int rev;
bool isrt();
void down();
int getwh()
{
return fu->ch[0]==this?0:1;
}
void set(int wh,tree *child);
}lct[maxn];
void tree::down()
{
if (rev)
{
rev=0;
swap(ch[0],ch[1]);
ch[0]->rev^=1;ch[1]->rev^=1;
}
}
void tree::set(int wh,tree *child)
{
ch[wh]=child;
if(child!=lct)child->fu=this;
down();
}
bool tree::isrt() //这段坑死了
{
if (fu==lct)
{
return 1;
}
return (fu->ch[0]!=this&&fu->ch[1]!=this);
}
void rotate(tree *now)
{
tree *fu=now->fu,*ye=now->fu->fu;
if (!(fu->isrt())) ye->down();//旋转的标记要提前下放
fu->down();now->down();//有序下放
int wh=now->getwh();
fu->set(wh,now->ch[wh^1]);
now->set(wh^1,fu);
now->fu=ye;
if(!ye->isrt())ye->ch[ye->ch[0]==fu?0:1]=now;
}
void splay(tree *now)
{
if(now->isrt()) return;
for (;!(now->isrt());rotate(now))
if(!(now->fu->isrt()))now->getwh()==now->fu->getwh()?rotate(now->fu):rotate(now);
}
tree *access(tree *now)
{
tree *y=lct;
for(;now!=lct;y=now,now=now->fu)
splay(now),now->down(),now->set(1,y);//建一路路径右儿子为重
return y;
}
void huan(tree *a)
{
access(a)->rev^=1;//根打标记
splay(a);//在子splay里面氚标记,做根
}
void link(tree *a,tree *b)
{
huan(a);//a换到根
a->fu=b;//把b放上去,相当于新建一棵splay
access(a);//a重新为根
}
void cut(tree *a,tree *b)
{
huan(a); //换为根
access(b); //b放到a右边,a在第二层
splay(a);
a->ch[1]=b->fu=lct;
}
tree *zhao(tree *a)
{
access(a);
splay(a);
tree *y=a;
while(y->ch[0]!=lct)y=y->ch[0];
return y;
}
int main()
{
int i;
scanf("%d%d",&n,&m);
lct->ch[0]=lct;
lct->ch[1]=lct;
lct->fu=lct;
lct->rev=0;
for (i=1;i<=n;i++)
{
(lct+i)->fu=(lct+i)->ch[0]=(lct+i)->ch[1]=lct;
(lct+i)->rev=0;
}
for (i=1;i<=m;i++)
{
scanf("%s",ss);
scanf("%d%d",&x,&y);
if(ss[0]=='C')
link(lct+x,lct+y);
if(ss[0]=='D')
{
cut(lct+x,lct+y);
//cout<<(lct+x)->ch[0];
}
if(ss[0]=='Q')
{
if(zhao(lct+x)==zhao(lct+y))printf("Yes\n");
else printf("No\n");
}
}
}