2017.3.31 洞穴勘测 思考记录

        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");
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值