[P3369]普通平衡树(Splay版)

模板,不解释

#include<bits/stdc++.h>
using namespace std;
const int mxn=1e5+5;
int fa[mxn],ch[mxn][2],sz[mxn],cnt[mxn],val[mxn],rt,tot;
namespace Splay {
    void push_up(int x) {
        sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
    };
    void rotate(int x) {
        int y=fa[x],z=fa[y],tp=ch[y][1]==x;
        ch[z][ch[z][1]==y]=x,fa[x]=z; //这里容易写错
        ch[y][tp]=ch[x][tp^1],fa[ch[x][tp^1]]=y;
        ch[x][tp^1]=y,fa[y]=x;
        push_up(y),push_up(x);
    };
    void splay(int x,int gl) {
        while(fa[x]!=gl) {
            int y=fa[x],z=fa[y];
            if(z!=gl)
                (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
            rotate(x);
        }
        if(gl==0) rt=x;
    };
    void find(int x) {
        int u=rt;
        while(ch[u][x>val[u]]/*这里不一定find的到该值,所以一定要加这句话*/&&x!=val[u]) u=ch[u][x>val[u]];
        splay(u,0);
    };
    int kth(int k) {
        int u=rt;
        while(1) {
            if(k<=sz[ch[u][0]]) u=ch[u][0];
            else if(k>sz[ch[u][0]]+cnt[u]) k-=sz[ch[u][0]]+cnt[u],u=ch[u][1];
            else return u;
        }
    };
    void ins(int x) {
        int u=rt,f=0;
        while(val[u]!=x&&u) f=u,u=ch[u][x>val[u]];
        if(u==0) {
            u=++tot;
            if(f) ch[f][x>val[f]]=u;
            val[u]=x; fa[u]=f;
            cnt[u]=sz[u]=1;
        }
        else ++cnt[u];
        splay(u,0);
    };
    int pre(int x) {
        find(x);
        if(val[rt]<x) return rt;
        int u=ch[rt][0];
        while(ch[u][1]) u=ch[u][1];
        return u;
    };
    int nxt(int x) {
        find(x);
        if(val[rt]>x) return rt;
        int u=ch[rt][1];
        while(ch[u][0]) u=ch[u][0];
        return u;
    };
    void erase(int x) {
        find(x);
        if(cnt[rt]>1) --cnt[rt];
        else {
            int l=pre(x),r=nxt(x); //这里容易写错
            splay(l,0); splay(r,l);
            ch[r][0]=0;
        }
    };
}

int main()
{
    using namespace Splay;
    int t,opt,x;
    scanf("%d",&t);
    ins(-1000000000),ins(1000000000);//切记插入端点,否则前驱后继不好求
    while(t--) {
        scanf("%d %d",&opt,&x);
        if(opt==1) ins(x);
        else if(opt==2) erase(x);
        else if(opt==3) find(x),printf("%d\n",sz[ch[rt][0]]);
        else if(opt==4) printf("%d\n",val[kth(x+1)]);
        else if(opt==5) printf("%d\n",val[pre(x)]);
        else printf("%d\n",val[nxt(x)]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/list1/p/10362914.html

时间: 2024-10-16 15:06:29

[P3369]普通平衡树(Splay版)的相关文章

【BZOJ3224】Tyvj 1728 普通平衡树 Splay

Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) Input 第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6) Output 对于操作3,4,5,6每行输

【转】 史上最详尽的平衡树(splay)讲解与模板(非指针版spaly)

ORZ原创Clove学姐: 变量声明:f[i]表示i的父结点,ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子,key[i]表示i的关键字(即结点i代表的那个数字),cnt[i]表示i结点的关键字出现的次数(相当于权值),size[i]表示包括i的这个子树的大小:sz为整棵树的大小,root为整棵树的根. 再介绍几个基本操作: [clear操作]:将当前点的各项值都清0(用于删除之后) inline void clear(int x){ ch[x][0]=ch[x][1]=f[x]

P3369 【模板】普通平衡树 (splay)

splay支持查询 1.第k大 2.第k大是谁 3.数的前驱 4.数的后继 5.添加删除 #include <bits/stdc++.h> using namespace std; int rt, cnt; int ch[100005][2]; //左右儿子 int fa[100005]; //父节点 int sz[100005]; //字树和 int cn[100005]; //当前点出现了多少次 int val[100005]; //当前点权值 void clear(int x) { sz

bzoj3224 普通平衡树(splay 模板)

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 11427  Solved: 4878[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

bzoj 1588 平衡树 splay

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 15446  Solved: 6076[Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其

Tyvj P1729 文艺平衡树 Splay

题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入格式 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数

BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

【BZOJ1125】【POI2008】Poc 原名:Train hash+离散化+平衡树(splay)

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/45739895"); } 题解: 首先我们发现对于每个串,我们把它hash一下,然后建一棵平衡树来支持"插入"."删除"."下传标记"这三种操作就可以记录并更新一个点的答案了

HYSBZ 3224 Tyvj 1728 普通平衡树 splay模版

先学了splay写的 以后有空再学treap和sbt版 参考: http://blog.csdn.net/clove_unique/article/details/50630280 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector>