刚学oi,60pts蒟蒻求调
查看原帖
刚学oi,60pts蒟蒻求调
469828
CeciliaWind楼主2022/10/7 08:15
#include <cstdio>
#include <algorithm>
#include <time.h>
#include <cstdlib>
#include <iostream>

using namespace std;

const int MAXN=1e6+50;
int n;
int tot;//树的大小
int lin,rt;
int l[MAXN<<2],r[MAXN<<2];
int val[MAXN<<2],cnt[MAXN<<2],size[MAXN<<2],key[MAXN<<2];

//更新以id位根节点的子树大小
void push_up(int id)
{
	size[id]=size[l[id]]+size[r[id]]+cnt[id];
}

//左旋操作
void left_rorate(int &u)//&u就是把u的地址取出来
{
	int t=r[u];
	r[u]=l[t];
	l[t]=u;
	size[t]=size[u];
	push_up(u);
	u=t;
}

//右旋操作
void right_rorate(int &u)
{
	int t=l[u];
	l[u]=r[t];
	r[t]=u;
	size[t]=size[u];
	push_up(u);
	u=t;
}

//在以u为根节点的子树中插入v
void insert(int &u,int v)
{
	if(!u)
		return (void)(size[u=++tot]=1,val[u]=v,cnt[u]=1,key[u]=rand());
	size[u]++;
	if(val[u]==v)
		return (void)(cnt[u]++);
	else if(val[u]<v)
	{
		insert(r[u],v);
		if(key[u]>key[r[u]])
			left_rorate(u);
	}
	else if(val[u]>v)
	{
		insert(l[u],v);
		if(key[u]>key[l[u]])
			right_rorate(u);
	}
	push_up(u);
}

//在以u为根节点的子树中删除v
bool Delete(int &u,int v)
{
	if(!u)
		return false;
	if(val[u]==v)
	{
		if(cnt[u]>1)
		{
			cnt[u]--,size[u]--;
			return true;
		}
		else if(!l[u] or !r[u])
		{
			u=l[u]+r[u];
			return true;
		}
		else if(key[l[u]]<key[r[u]])
		{
			right_rorate(u);
			return Delete(u,v);
		}
		else
		{
			left_rorate(u);
			return Delete(u,v);
		}
	}
	else if(val[u]<v)
	{
		bool flag=Delete(r[u],v);
		if(flag)
			size[u]--;
		return flag;
	}
	else if(val[u]>v)
	{
		bool flag=Delete(l[u],v);
		if(flag)
			size[u]--;
		return flag;
	}
	push_up(u);
}

//查询v的排名
int ask_rank(int u,int v)
{
	if(!u)
		return 1;
	if(val[u]==v)
		return size[l[u]]+1;
	else if(val[u]<v)
		return size[l[u]]+cnt[u]+ask_rank(r[u],v);
	else if(val[u]>v)
		return ask_rank(l[u],v);
}

//查询排名为v的数
int find_rank(int u,int v)
{
	if(!u)
		return 0;
	if(size[l[u]]+1==v)
		return val[u];
	else if(size[l[u]]>=v)
		return find_rank(l[u],v);
	else if(size[l[u]]+cnt[u]<v)
		return find_rank(r[u],v-size[l[u]]-cnt[u]);
}

void ask_pre(int u,int x)
{
	if(!u)
		return;
	if(val[u]<x)
		lin=u,ask_pre(r[u],x);
	else
		ask_pre(l[u],x);
}

void ask_net(int u,int x)
{
	if(!u)
		return;
	if(val[u]>x)
		lin=u,ask_net(l[u],x);
	else
		ask_net(r[u],x);
}

int pre(int x)
{
	ask_pre(rt,x);
	return val[lin];
}

int net(int x)
{
	ask_net(rt,x);
	return val[lin];
}

int main()
{
	// srand(time(NULL));
	scanf("%d",&n);
	// int hhd=1;
	for(int i=1,c,x;i<=n;i++)
	{
		scanf("%d%d",&c,&x);
		switch(c)
		{
			case 1:
				insert(rt,x);break;
			case 2:
				Delete(rt,x);break;
			case 3:
				printf("%d\n",ask_rank(rt,x));break;
			case 4:
				printf("%d\n",find_rank(rt,x));break;
			case 5:
				printf("%d\n",pre(x));break;
			case 6:
				printf("%d\n",net(x));break;
			default:
				break;
		}
	}
}

每次输出的错误答案都不一样,

2022/10/7 08:15
加载中...