bzoj 3224==tyvj 1728普通平衡树 splay

32 篇文章 0 订阅
10 篇文章 0 订阅

啊啊啊啊今天各种煞笔啊。。

首先早晨起晚了。。一晚上从11点睡到了7点。。

下午大概三点半开始写这个题。。各种不顺以后发现70分一直超时。。各种方法都不行,后来直接把lyw的子程序都闹过来结果成60 了。。。

最后在6点20 的时候发现了一个恶心的问题!!!!

应该用printf但是我用的是cout!!!!!

当时为了偷懒所以就说先用cout吧,最后就忘了。。。不行不行以后5个数以上都要用cstdio里的东西

这个大概可以作为splay的一般模版了吧。。

下面是代码(话说今天debug的技巧又学了一些)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define MAX 100086

using namespace std;

int child[MAX][2],father[MAX],cnt[MAX],size[MAX],value[MAX];
int n,i,a1,a2,num=0,root;

void rotate(int p)
{
	//cout<<"rotate"<<endl;
	int q=father[p],y=father[q],x=(child[q][1]==p);
	//if p is q's right person then x==1 else x==0
	//if x==1 then rotate_left
	//else if x==0 then rotate_right
	father[child[q][x]=child[p][x^1]]=q;
	father[child[p][x^1]=q]=p;
	father[p]=y;
	if(y)
	 child[y][child[y][1]==q]=p;
	size[q]=cnt[q]+size[child[q][0]]+size[child[q][1]];
	size[p]=cnt[p]+size[child[p][0]]+size[child[p][q]];
	//pay more attention = = -> the size of p,q should re_calc
}

void splay(int x,int aim=0)
{
	//cout<<"splay"<<endl;
	for(int y;(y=father[x])!=aim;rotate(x))
	 if(father[y]!=aim)
	  {
	  	if((child[y][0]==x)==(child[father[y]][0]==y))	  	  
	  	  	rotate(y);	  	  
	  	else
	  	   rotate(x);
	  }
	if(aim==0)
	  root=x;
/*	for(int y;(y=father[x])!=aim;rotate(x))
		if(father[y]!=aim)rotate((child[y][0]==x)==(child[father[y]][0]==y)?y:x);
	if(aim==0)root=x;*/
	
	size[x]=size[child[x][0]]+cnt[x]+size[child[x][1]];
} 

void insert(int x,int k)
{
	if(!x)
	 {
	 	num++;
	 	root=num;
	 	x=num;
		value[x]=k;
	 	father[x]=0;
	 	child[x][1]=child[x][0]=0;
	 	
	 	cnt[x]=1;
	 	size[x]=1;	
		 return; 	
	 }
	while(x)
	 {
	 	size[x]++;
	 	if(k==value[x])
	 	 {
	 	 	cnt[x]++;
	 	 	return;
	 	 }
	 	int &y=child[x][k>value[x]];
	 	if(!y)
	 	 {
	 	 	num++;
	 	 	y=num;
	 	 	father[y]=x;
	 	 	child[y][0]=child[y][1]=0;
	 	 	cnt[y]=size[y]=1;
	 	 	value[y]=k;
	 	 	break;
	 	 }
	 	x=y;
	 }
	splay(x);
}

void insert_(int x,int v)
{
	if(x==0){root=x=++num;value[x]=v;father[x]=child[x][0]=child[x][1]=0;size[x]=cnt[x]=1;return;}
	while(x)
	{
		size[x]++;
		if(v==value[x]){cnt[x]++;return;}
		int &y=child[x][v>=value[x]];
		if(y==0){y=++num;value[y]=v;father[y]=x;child[y][0]=child[y][1]=0;size[y]=cnt[y]=1;x=y;break;}
		x=y;
	}
	splay(x);
}

int rank_(int x,int k)
{
	int ret=0;
	while(x)
	 {
	 	if(k>value[x])
	 	 {
	 	 	ret+=size[child[x][0]]+cnt[x];
	 	 	x=child[x][1];
	 	 }
	 	else
	 	 {
	 	 	if(k==value[x])
	 	 	 return ret+size[child[x][0]]+1;
	 	 	else
	 	 	 x=child[x][0];
	 	 }
	 }
}

int r_th(int x,int k)
{
	while(x)
	 {
	 	if(k>=size[child[x][0]]+1&&k<=size[child[x][0]]+cnt[x])
	 	  return value[x];
	 	if(k>size[child[x][0]]+cnt[x])
	 	 {
	 	 	k-=size[child[x][0]]+cnt[x];
	 	 	x=child[x][1];
	 	 }
	 	else
	 	 x=child[x][0];
	 }
}

int pre(int x,int k)
{
	int ans;
	while(x)
	 {
	 	if(value[x]<k)
	 	 {
	 	 	ans=value[x];
	 	 	x=child[x][1];
	 	 }
	 	else
	 	 x=child[x][0];
	 }
	return ans;
}

int suc(int x,int k)
{
	int ans;
	while(x)
	 {
	 	if(value[x]>k)
	 	 {
	 	 	ans=value[x];
	 	 	x=child[x][0];
	 	 }
	 	else
	 	 x=child[x][1];
	 }
	return ans;
}

void debug()
{
	cout<<root<<' '<<value[root]<<' '<<value[child[root][0]]<<' '<<value[child[root][1]]<<endl;
	cout<<root<<' '<<size[root]<<' '<<size[child[root][0]]<<' '<<size[child[root][1]]<<endl;
	cout<<root<<' '<<cnt[root]<<' '<<cnt[child[root][0]]<<' '<<cnt[child[root][1]]<<endl;
}

void read_work_print()
{
	cin>>n;
	while(n--)
	 {
	 	//debug();
	 	scanf("%d%d",&a1,&a2);
	 	switch(a1)
	 	{
	 	 case 1:
	 	 	 {
	 	 	 	insert(root,a2);
	 	 	 	break;
	 	 	 }
	 	case 2:
	 	 	 {
	 	 	 	delete_(root,a2);
	 	 	 	break;
	 	 	 }
	 	case 3:
	 	 	 {
	 	 	 	printf("%d\n",rank_(root,a2));
	 	 	 	break;
	 	 	 }
	 	case 4:
	 	 	 {
	 	 	 	printf("%d\n",r_th(root,a2));
	 	 	 	break;
	 	 	 }
	 	case 5:
	 	 	 {
	 	 	 	printf("%d\n",pre(root,a2));
	 	 	 	break;
	 	 	 }
	 	case 6:
	 	 	 {
	 	 	 	printf("%d\n",suc(root,a2));
	 	 	 	break;
	 	 	 }
	   }
	 }
}

int main()
{
	read_work_print();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值