P3369 【模板】普通平衡树 [替罪羊树做法]

R e s u l t Result Result

...


H y p e r l i n k Hyperlink Hyperlink

https://www.luogu.org/problemnew/show/P3369


D e s c r i p t i o n Description Description

写一种数据结构维护一些数据
包括插入,查找,删除,查找前驱,查找后继等


S o l u t i o n Solution Solution

好久之前扣 T r e a p Treap Treap过了这道题,后来坐我旁边那位大佬写了替罪羊树,赶紧去%%%,终于%到了这篇题解


C o d e Code Code
#include<cctype>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{int lson,rson,val,valid,total;bool ok;}t[2000001];
int nc[2000001],cz[2000001],root,lnc,lcz,buildwho,x,opt,m;
inline char Getchar()
{
    static char buf[1000000],*p1=buf+1000000,*pend=buf+1000000;
    if(p1==pend)
	{
        p1=buf; pend=buf+fread(buf,1,1000000,stdin);
        if (pend==p1) return -1;
    }
    return *p1++;
}
inline long long read()
{
	char c;int d=1;long long f=0;
	while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
inline void write(register long long x)
{
	if(x<0)putchar(45),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+48);
	return;
}
inline bool isbad(int k)//是否需要重构
{
	if((double)t[k].valid*0.8<=(double)max(t[t[k].lson].valid,t[t[k].rson].valid)) return true;
	return false;
}
void dfs(int k)//中序遍历
{
	if(!k) return;
	dfs(t[k].lson);
	if(t[k].ok) cz[++lcz]=k;else nc[++lnc]=k;
	dfs(t[k].rson);
	return;
}
void build(int l,int r,int &k)//建树
{
	int mid=l+r>>1;
	k=cz[mid];
	if(l==r)
	{
		t[k].lson=t[k].rson=0;
		t[k].total=t[k].valid=1;
		return;
	}
	if(l<mid) build(l,mid-1,t[k].lson);else t[k].lson=0;
	build(mid+1,r,t[k].rson);
	t[k].total=t[t[k].lson].total+t[t[k].rson].total+1;
	t[k].valid=t[t[k].lson].valid+t[t[k].rson].valid+1;
	return;
}
inline void rebuild(int &k)//重建
{
	lcz=0;
	dfs(k);
	if(lcz) build(1,lcz,k);else k=0;
	return;
}
inline int find_rank(int k)//查找k的排名
{
	int now=root,ans=1;
	while(now)
	{
		if(t[now].val>=k) now=t[now].lson;//在左边
		else
		{
			ans+=t[t[now].lson].valid+t[now].ok;//往右边走要加上排名
			now=t[now].rson;
		}
	}
	return ans;
}
inline int find_kth(int k)//查找排名为k的数
{
	int now=root;
	while(now)
	{
		if(t[now].ok&&t[t[now].lson].valid+1==k) return t[now].val;//找到啦
		if(t[t[now].lson].valid>=k) now=t[now].lson;//左边
		else
		{
			k-=t[t[now].lson].valid+t[now].ok;//往右边走要减去排名
			now=t[now].rson;//走啊
		}
	}
	return -1;
}
void insert(int &k,int x)//插入
{
	if(!k)//没有根则新建
	{
		k=nc[lnc--];t[k].val=x;
		t[k].ok=t[k].total=t[k].valid=1;
		t[k].lson=t[k].rson=0;
		return;
	}
	t[k].total++;t[k].valid++;
	if(t[k].val>=x) insert(t[k].lson,x);
	else insert(t[k].rson,x);
	if(isbad(k)) rebuild(k);//不平衡则重构
}
void delet_pos(int &k,int x)//删除排名为x的数
{
	if(t[k].ok&&t[t[k].lson].valid+1==x) {t[k].ok=0;t[k].valid--;return;}
	t[k].valid--;
	if(t[t[k].lson].valid+t[k].ok>=x) delet_pos(t[k].lson,x);
	else delet_pos(t[k].rson,x-(t[t[k].lson].valid+t[k].ok));
	return;	
}
void delet_val(int x)//删除这个数
{
	delet_pos(root,find_rank(x));
	if((double)t[root].total*0.8>t[root].valid) rebuild(root);
	return;
}
signed main()
{
	for(register int i=2000000;i>0;i--) nc[++lnc]=i;
	m=read();
	while(m--)
	{
		opt=read();x=read();
		if(opt==1) insert(root,x);
		if(opt==2) delet_val(x);
		if(opt==3) write(find_rank(x)),putchar(10);
		if(opt==4) write(find_kth(x)),putchar(10);
		if(opt==5) write(find_kth(find_rank(x)-1)),putchar(10);
		if(opt==6) write(find_kth(find_rank(x+1))),putchar(10);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值