列表

详情


NC17318. 红黑树期望旋转次数

描述

维护一棵初始为空的红黑树,进行n次操作。
对于重复的整数,我们认为插入时间晚的一个更小。
操作有两类:
op=1:在红黑树上插入一个整数x;
op=2:给出x,询问从1到x的整数中等概率选取一个插入到红黑树上,造成的旋转次数的期望值,方便起见,你只要输出 期望值*x,(可以证明这是一个整数)。

输入描述

第一行一个整数n;
接下来n行,每行两个由空格分隔的整数op,x,表示一次操作。
1≤n≤200000
1≤op≤2
1≤x≤100000000

输出描述

对每个op=2的操作,输出一行,包含一个整数,表示答案

示例1

输入:

10
2 5
1 3
1 4
2 3
2 4
2 5
1 4
2 3
2 4
2 5

输出:

0
0
2
3
0
0
0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 206ms, 内存消耗: 22364K, 提交时间: 2018-07-20 22:02:24

#include<bits/stdc++.h>
struct node;
typedef node* pn;
struct node{
	pn c[2];
	int l,r;
	bool red,nil;
	int ans,cl,cr,b2r;
	void col(int c){
		red=c;
		up();
	}
	void black_down(){
		c[0]->col(0);
		c[1]->col(0);
		col(1);
	}
	void up(){
		ans=c[0]->ans+c[1]->ans;
		if(red){
			cl=c[0]->b2r;
			cr=c[1]->b2r;
			b2r=0;
		}else{
			cl=cr=b2r=0;
			if(c[1]->red)b2r+=(c[0]->cl+c[0]->cr);
			else ans+=c[0]->cl+c[0]->cr*2;
			if(c[0]->red)b2r+=(c[1]->cl+c[1]->cr);
			else ans+=c[1]->cr+c[1]->cl*2;
		}
	}
}ns[1000007],*rt,*np=ns;
pn range(int l,int r){
	node*w=np++;
	w->c[0]=w->c[1]=ns;
	w->l=l;
	w->r=r;
	w->red=0;
	w->nil=1;
	w->ans=w->cl=w->cr=0;
	w->b2r=r-l+1;
	return w;
}
pn leaf(pn rt,int x){	
	pn w=np++;
	w->c[0]=range(rt->l,x);
	w->c[1]=range(x+1,rt->r);
	w->l=w->r=x;
	w->nil=0;
	w->col(1);
	return w;
}
void rot(pn& w,int d){
	pn u=w->c[d];
	w->c[d]=u->c[!d];
	u->c[!d]=w;
	std::swap(w->red,u->red);
	w->up();
	w=u;
	w->up();
}
void ins(pn& rt,int x){
	if(rt->nil){
		rt=leaf(rt,x);
		return;
	}
	int d=x>rt->l;
	pn& w=rt->c[d];
	ins(w,x);
	rt->up();
	if(w->red){
		if(w->c[d]->red){
			if(rt->c[!d]->red)rt->black_down();
			else rot(rt,d);
		}else if(w->c[!d]->red){
			if(rt->c[!d]->red)rt->black_down();
			else rot(w,!d),rot(rt,d);
		}
	}
}
pn get(pn rt,int x){
	if(rt->nil)return range(rt->l,std::min(rt->r,x));
	node*w=np++;
	*w=*rt;
	if(x>w->l)w->c[1]=get(w->c[1],x);
	else{
		w->c[0]=get(w->c[0],x);
		node*u=np++;
		*u=*w->c[1];
		u->ans=u->cl=u->cr=u->b2r=0;
		w->c[1]=u;
	}
	w->up();
	return w;
}
int _(int l,int r){
	int x=0;
	if(scanf("%d",&x)==1&&l<=x&&x<=r)return x;
	assert(0); 
}
int main(){
	range(1,0);
	rt=range(1,1e8);
	for(int n=_(1,200000),op,x;n--;){
		op=_(1,2);
		x=_(1,1e8);
		if(op==1){
			ins(rt,x);
			rt->col(0);
		}else{
			pn np0=np,tmp=get(rt,x);
			printf("%d\n",tmp->ans);
			np=np0;
		}
	}
	return 0;
}

上一题