记录编号 501419 评测结果 AAAAAAAAAA
题目名称 [Tyvj 1728]普通平衡树 最终得分 100
用户昵称 Gravatar_WA自动机 是否通过 通过
代码语言 C++ 运行时间 0.263 s
提交时间 2018-07-21 20:41:21 内存使用 0.31 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<climits>
#include<cstdlib>
#include<ctime>
struct node
{
	int v,cnt,rank,s;
	node *ch[2];
	node(int v):v(v),cnt(1),s(1),rank(rand()){ch[0]=ch[1]=0;}
	void MT()
	{
		s=cnt;
		if (ch[0]) s+=ch[0]->s;
		if (ch[1]) s+=ch[1]->s;
	}
	int cmp(int x)
	{
		if (x==v) return -1;
		return v<x;
	}
}*root;
void rotate(node* &o,int d)
{
	node* k=o->ch[d^1];
	o->ch[d^1]=k->ch[d];
	k->ch[d]=o;
	o->MT();
	k->MT();
	o=k;
}
void insert(node* &o,int v)
{
	if (!o) {o=new node(v);return;}
	int d=o->cmp(v);
	if (d==-1) {++o->cnt;++o->s;return;}
	insert(o->ch[d],v);
	if (o->ch[d]->rank>o->rank) rotate(o,d^1);
	o->MT();
}
void remove(node* &o,int v)
{
	int d=o->cmp(v);
	if (d==-1)
	{
		if (o->cnt>1) {--o->cnt;--o->s;return;}
		if (!(o->ch[0])) {node* k=o;o=o->ch[1];delete k;}
		else if (!(o->ch[1])) {node* k=o;o=o->ch[0];delete k;}
		else
		{
			int d2=o->ch[0]->rank>o->ch[1]->rank;
			rotate(o,d2);
			remove(o->ch[d2],v);
		}
	}
	else remove(o->ch[d],v);
	if (o) o->MT();
}
int rank(int x,node* o=root)
{
	if (!o) return INT_MAX;
	int s=o->ch[0]?o->ch[0]->s:0;
	if (o->v==x) return s+1;
	if (o->v>x) return rank(x,o->ch[0]);
	if (o->v<x) return rank(x,o->ch[1])+s+o->cnt; 
}
int kth(int k,node* o=root)
{
	if (!o) return INT_MIN;
	int s=o->ch[0]?o->ch[0]->s:0;
	if (k>s && k<=s+o->cnt) return o->v;
	if (k<=s) return kth(k,o->ch[0]);
	return kth(k-s-o->cnt,o->ch[1]);
}
int prec,succ;
void pre(int x,node* o=root)
{
	if (!o) return;
	if (o->v>prec && o->v<x) prec=o->v;
	if (o->v>=x) pre(x,o->ch[0]);
		else pre(x,o->ch[1]); 
}
void suc(int x,node* o=root)
{
	if (!o) return;
	if (o->v<succ && o->v>x) succ=o->v;
	if (o->v<=x) suc(x,o->ch[1]);
		else suc(x,o->ch[0]);
}
int main()
{
	freopen("phs.in","r",stdin);
	freopen("phs.out","w",stdout);
	srand(time(0));
	int n;
	int opt,x;
	scanf("%d",&n);
	while (n--)
	{
		scanf("%d%d",&opt,&x);
		switch (opt)
		{
			case 1:insert(root,x);break;
			case 2:remove(root,x);break;
			case 3:printf("%d\n",rank(x));break;
			case 4:printf("%d\n",kth(x));break;
			case 5:prec=INT_MIN;pre(x);printf("%d\n",prec);break;
			case 6:succ=INT_MAX;suc(x);printf("%d\n",succ);
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}