bzoj3223==tyvj1729 文艺平衡树

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

这个水题应该算是用splay处理区间问题的入门了吧。。。昨天从早晨到晚上一直都在考虑优先级的问题,后来看到网上大神说的才理解,在splay的区间问题里,做价值的并不是数值而是他在整个区间的下标也就是第几个,这个理解了以后今天早晨看的标程写的。。。

下面是代码

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

using namespace std;

int n,i,m,tot=0,top=0;
int size[MAX],child[MAX][2],father[MAX],value[MAX],res[MAX];
int root=0,num=0;
int a[MAX];

void down(int x)
{
	if(!x)
		return;
	if(!res[x])
		return;
	if(child[x][0])
		res[child[x][0]]^=1;	
	if(child[x][1])
		res[child[x][1]]^=1;
	res[x]=0;
	swap(child[x][0],child[x][1]);
}

void rotate(int p)
{
	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
	
	down(q);
	down(p);
	//pay attention !

	father[child[q][x]=child[p][x^1]]=q;
	father[child[p][x^1]=q]=p;
	father[p]=y;
	//res[p]=0;
	if(y)
	 child[y][child[y][1]==q]=p;
	size[q]=1+size[child[q][0]]+size[child[q][1]];
	size[p]=1+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)
{
	down(x);
	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;	
	size[x]=size[child[x][0]]+1+size[child[x][1]];	
}

/*int ask(int x,int k)//select
{
	k--;	
	for(;;)
	 {
	 	if(x==0)
	 	  return 0;
	 	if(size[child[x][1]]<=k&&k<cnt[x]+size[child[x][1]])
	 	  return x;
	 	if(size[child[x][1]]>k)
	 	  x=child[x][1];
	 	else
	 	 {
	 	 	k-=cnt[x]+size[child[x][1]];
	 	 	x=child[x][0];
	 	 }
	 }
}

void up_date(int x)
{
	if(!x)
		return;
	if(res[x])
	{
		res[x]=0;
		swap(child[x][1],child[x][0]);
		swap(value[child[x][0]],value[child[x][1]]);
		res[child[x][1]]=!res[child[x][1]];
		res[child[x][0]]=!res[child[x][0]];
	}
}

void reserve(int l,int r)
{
	splay(ask(root,n-(l-1)+1));
	splay(ask(root,n-(r+1)+1),root);
	child[child[root][1]][0]^=1;
	up_date(child[child[root][1]][0]);
}*/

void print(int x)
{
//	cout<<"print="<<x<<endl;
	if(!x)
		return;
	down(x);
	print(child[x][0]);
	printf("%d ",value[x]);
	print(child[x][1]);
	return;
}

void update(int x)
{
	if(!x)
		return;
	size[x]=size[child[x][0]]+size[child[x][1]]+1;
}

int select(int k)
{
	int t=root;
	while(1)
	{
		down(t);
		if(size[child[t][0]]+1==k)
			break;
		if(k<=size[child[t][0]])
			t=child[t][0];
	    else
		{
			k-=size[child[t][0]]+1;
			t=child[t][1];
		}
	}
	return t;
}

void build(int &x,int l,int r)
{
	if(l>r)
	{
		x=0;
		return;
	}
	int mid=(l+r)/2;
	tot++;
	x=tot;
	size[x]=1;
	res[x]=0;
	value[x]=a[mid];
	build(child[x][0],l,mid-1);
	build(child[x][1],mid+1,r);
	if(child[x][0])
		father[child[x][0]]=x;
    if(child[x][1])
		father[child[x][1]]=x;
	update(x);
}

void debug()
{
	for(int k=1;k<=tot;k++)
		printf("%d %d %d %d\n",k,father[k],child[k][0],child[k][1]);
}

int main()
{
	scanf("%d%d",&n,&m);
	for(i=1;i<=n+2;i++) 
		a[i]=i-1;
	root=tot=0;
	size[0]=0;
	build(root,1,n+2);
	//debug();
	int y1,y2;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&y1,&y2);
		splay(select(y1));
		splay(select(y2+2),root);
		res[child[child[root][1]][0]]^=1;
		down(child[child[root][1]][0]);
	}
	splay(select(1));
	splay(select(n+2),root);	
	print(child[child[root][1]][0]);
    printf("\n");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值