• 【洛谷P3369】【模板】普通平衡树


    题目

    题目链接:https://www.luogu.com.cn/problem/P3369
    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1. 插入 (x)
    2. 删除 (x) 数(若有多个相同的数,因只删除一个)
    3. 查询 (x) 数的排名(排名定义为比当前数小的数的个数 (+1) )
    4. 查询排名为 (x) 的数
    5. (x) 的前驱(前驱定义为小于 (x),且最大的数)
    6. (x) 的后继(后继定义为大于 (x),且最小的数)

    (nleq 10^5,|x|leq 10^7)

    思路

    Splay Treap
    FHQ-Treap。
    推荐 Blog
    两个核心操作:split 和 merge。
    split 把一棵 Treap 分成两棵,一般有按照前 (k) 个分和按照权值分。
    merge 把两棵 Treap 合并成一棵。
    通过这两个操作就可以完成平衡树各种其他操作。具体见代码。
    时间复杂度 (O(nlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=100010;
    int n,rt;
    
    struct FHQ
    {
    	int tot,ch[N][2],val[N],siz[N],dat[N];
    	
    	void pushup(int x)
    	{
    		siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    	}
    	
    	int New(int v)
    	{
    		int x=++tot;
    		val[x]=v; siz[x]=1; dat[x]=rand();
    		return x;
    	}
    	
    	void split(int x,int k,int &lc,int &rc)
    	{
    		if (!x) { lc=rc=0; return; }
    		if (val[x]<=k)
    			lc=x,split(ch[x][1],k,ch[x][1],rc);
    		else
    			rc=x,split(ch[x][0],k,lc,ch[x][0]);
    		pushup(x);
    	}
    	
    	int merge(int x,int y)
    	{
    		if (!x || !y) return x|y;
    		if (dat[x]>dat[y])
    		{
    			ch[x][1]=merge(ch[x][1],y);
    			pushup(x);
    			return x;
    		}
    		else
    		{
    			ch[y][0]=merge(x,ch[y][0]);
    			pushup(y);
    			return y;
    		}
    	}
    	
    	void ins(int v)
    	{
    		int x,y;
    		split(rt,v,x,y);
    		rt=merge(merge(x,New(v)),y);
    	}
    	
    	void del(int v)
    	{
    		int x,y,z;
    		split(rt,v,x,y); split(x,v-1,x,z);
    		z=merge(ch[z][0],ch[z][1]);
    		rt=merge(merge(x,z),y);
    	}
    	
    	int getrk(int v)
    	{
    		int x,y,z;
    		split(rt,v-1,x,y);
    		z=siz[x];
    		rt=merge(x,y);
    		return z+1;
    	}
    	
    	int getval(int x,int k)
    	{
    		if (siz[ch[x][0]]==k-1) return val[x];
    		if (siz[ch[x][0]]>=k) return getval(ch[x][0],k);
    			else return getval(ch[x][1],k-siz[ch[x][0]]-1);
    	}
    	
    	int pre(int v)
    	{
    		int x,y,z;
    		split(rt,v-1,x,y);
    		z=getval(x,siz[x]);
    		rt=merge(x,y);
    		return z;
    	}
    	
    	int nxt(int v)
    	{
    		int x,y,z;
    		split(rt,v,x,y);
    		z=getval(y,1);
    		rt=merge(x,y);
    		return z;
    	}
    }fhq;
    
    int main()
    {
    	srand(171023);
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    	{
    		int opt,x;
    		scanf("%d%d",&opt,&x);
    		if (opt==1) fhq.ins(x);
    		if (opt==2) fhq.del(x);
    		if (opt==3) printf("%d
    ",fhq.getrk(x));
    		if (opt==4) printf("%d
    ",fhq.getval(rt,x));
    		if (opt==5) printf("%d
    ",fhq.pre(x));
    		if (opt==6) printf("%d
    ",fhq.nxt(x));
    	}
    	return 0;
    }
    
  • 相关阅读:
    python使用suds来调用webservice
    第二章 :初识MySQL
    什么是端口概念?
    数据库中的五种约束
    MySQL基本概念以及简单操作
    Java 持久化操作之 --XML
    Soso(嗖嗖)移动 java 项目
    Java多线程笔记总结
    java中代码的注释和快捷
    java oop 单列 双列 集合, 迭代器 的使用和说明
  • 原文地址:https://www.cnblogs.com/stoorz/p/14301838.html
Copyright © 2020-2023  润新知