【模板】Splay

机器视觉最全面试题总结 空洞卷积(Atrous Convolution)也叫做膨胀卷积、扩张卷积,最初的提出是为了解决图像分割在用下采样(池化、卷积)增加感受野时带来的特征图缩小,后再上采样回去时造成的精度上的损失。空洞卷积通过引入了一个扩张率的超参数,该参数定义了卷积核处理数据时各值的间距。可以在增加感受野的同时保持特征图的尺寸不变,从而代替下采样和上采样a. 是普通的卷积过程(dilation rate = 1),卷积后的感受野为3b. 是dilation rate = 2的空洞卷积,卷积后的感受野为5。 阅读详情

题目链接:
洛谷 P3369 【模板】普通平衡树(Treap/SBT)
BZOJ 3224: Tyvj 1728 普通平衡树


第一次尝试

第一次splay板子是大佬教给我的,全部用指针完成了splay的基本操作。当时的我码力还是不足,调试了半天极其低级的错误,当时的我还把他们记载在下面:

  • [attempt 1] CE 由于构造函数未在结构体里声明
struct node
{
    int val,siz,cnt;
    node *son[2],*fa;
    node(const int &k);     //<-this line.
    int dir(){return fa->son[1]==this;}
    void upd(){siz=son[0]->siz+son[1]->siz+cnt;}
}*nil=new node(0),*RT,*flag;
node::node(const int &k)
{
    val=k,siz=cnt=1,son[0]=son[1]=fa=nil;
}
  • [attempt 2] WA rotate函数错误
void rotate(node *rt,int d)
{
    node *t=rt->son[d^1];
    rt->son[d^1]=t->son[d];
    if(rt->son[d^1]!=nil)rt->son[d^1]->fa=rt;
    t->son[d]=rt;    //<-this line.
    if(rt->fa!=nil)rt->fa->son[rt->dir()]=t;
    t->fa=rt->fa;rt->fa=t;
    rt->upd();t->upd();
    return;
}
  • [attempt 3] WA delete函数错误
void del(int x)
{
    node *l=lower(RT,x),*r=upper(RT,x);
    if(l==nil&&r==nil)
    {
        if(RT->cnt==1)RT=nil;
        else RT->cnt--,RT->siz--;
        return;
    }
    if(l==nil&&r!=nil)
    {
        splay(r,nil);
        if(RT->son[0]->cnt==1)RT->son[0]=nil;
        else RT->son[0]->cnt--,RT->son[0]->siz--;
        RT->upd();
        return;
    }
    if(r==nil)
    {
        splay(l,nil);
        if(RT->son[1]->cnt==1)RT->son[1]=nil;
        else RT->son[1]->cnt--,RT->son[1]->siz--;
        RT->upd();
        return;
    }
    splay(l,nil);
    splay(r,RT);
    node *obj=RT->son[1]->son[0];
    if(obj->cnt==1)RT->son[1]->son[0]=nil;
    else obj->cnt--,obj->siz--;
    RT->son[1]->upd();
    RT->upd();
    return;
}

这里我调试了很久,比如虚拟节点不能update更新子树大小,再比如删除时只更新了临时变量,没有更改其父亲的儿子指针等等。


第二次尝试

这一次的我经历了一年多的沉淀然而还是那么菜,选择了用数组完成splay这个数据结构。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
inline int read(){
  int x=0,y=1;char c=getchar();
  while(!isdigit(c)){if(c=='-')y=-y;c=getchar();}
  while(isdigit(c)){x=x*10+c-'0';c=getchar();}
  return x*y;
}

const int INF = 100000000;
const int MAXN = 100010;
int son[MAXN][2],fa[MAXN];
int siz[MAXN],rev[MAXN],cnt[MAXN],key[MAXN];
int tot,root;

int getd(int x){return son[fa[x]][1] == x;}

int push_up(int x){
  siz[x] = siz[son[x][0]] + siz[son[x][1]] + cnt[x];
  return 0;
}
void push_down(int x){
  if(rev[x]){
    rev[x]^=1,rev[son[x][0]]^=1,rev[son[x][1]]^=1;
    swap(son[x][0],son[x][1]);
  }
}

void rotate(int x){
  int fat=fa[x],gra=fa[fat],dir=getd(x),fad=getd(fat);
  son[fat][dir]=son[x][dir^1];
  fa[son[x][dir^1]]=fat;
  son[x][dir^1]=fat;
  fa[fat]=x;
  if(gra)son[gra][fad]=x;
  fa[x]=gra;
  push_up(fat);
  push_up(x);
}
int splay(int x,int to){
  while(fa[x]!=to){
    if(fa[fa[x]]!=to&&getd(fa[x])==getd(x))rotate(fa[x]);
    rotate(x);
  }
  if(to==0)root=x;
  return 0;
}

void init(){
  key[1]=-INF,key[2]=INF;
  siz[1]=1,siz[2]=2;
  cnt[1]=cnt[2]=1;
  fa[1]=2,son[2][0]=1;
  root=tot=2;
}

int insert(int now,int fat,int dir,int k){
  if(now==0){
    fa[++tot]=fat,son[fat][dir]=tot;
    cnt[tot]=siz[tot]=1;
    key[tot]=k;
    return tot;
  }
  if(key[now]==k){
    siz[now]++;
    cnt[now]++;
    return now;
  }
  if(key[now]>k)return insert(son[now][0],now,0,k)+push_up(now);
  if(key[now]<k)return insert(son[now][1],now,1,k)+push_up(now);
  return 0;
}

int Find(int now,int x){
  if(now==0)return 0;
  if(key[now]==x)return now;
  if(key[now]>x)return Find(son[now][0],x);
  if(key[now]<x)return Find(son[now][1],x);
}

int get_rank(int now,int k){
  if(now==0)return printf("error\n");
  if(key[now]==k)return siz[son[now][0]]+1;
  if(key[now]>k)return get_rank(son[now][0],k);
  if(key[now]<k)return get_rank(son[now][1],k)+siz[now]-siz[son[now][1]];
  return 0;
}

int find_rank(int now,int k){
  if(now==0)return 0;
  const int L=siz[son[now][0]],N=cnt[now],R=siz[son[now][1]];
  if(k<=L)return find_rank(son[now][0],k);
  if(L<k&&k<=L+N){splay(now,0);return key[now];}
  if(k>L+N)return find_rank(son[now][1],k-L-N);
}

inline int max_key(int x,int y){key[0]=-INF;return key[x]>key[y]?x:y;}
int prev(int now,int k){
  if(now==0)return 0;
  if(key[now]>=k)return prev(son[now][0],k);
  return max_key(prev(son[now][1],k),now);
}

inline int min_key(int x,int y){key[0]=INF;return key[x]<key[y]?x:y;}
int next(int now,int k){
  if(now==0)return 0;
  if(key[now]<=k)return next(son[now][1],k);
  return min_key(next(son[now][0],k),now);
}

int Delete(int k){
  splay(prev(root,k),0);
  splay(next(root,k),root);
  int t=son[son[root][1]][0];
  if(cnt[t]>1){cnt[t]--;siz[t]--;}
  else son[son[root][1]][0]=0;
  push_up(son[root][1]);
  push_up(root);
}

int main(){
  init();
  int n=read();
  while(n--){
    int opt=read(),x=read();
    switch(opt){
      case 1:{
        splay(insert(root,0,0,x),0);
        break;
      }
      case 2:{
        Delete(x);
        break;
      }
      case 3:{
        printf("%d\n",get_rank(root,x)-1);
        splay(Find(root,x),0);
        break;
      }
      case 4:{
        printf("%d\n",find_rank(root,x+1));
        break;
      }
      case 5:{
        printf("%d\n",key[prev(root,x)]);
        break;
      }
      case 6:{
        printf("%d\n",key[next(root,x)]);
        break;
      }
    }
    //for(int i=1;find_rank(root,i)!=INF;i++){
    //  printf("%d ",find_rank(root,i));
    //}
    //printf("\n");
  }
}

关于splay的删除,网上的版本不一,但经过我的搜索,最快的应该是下面这种:

splay的最快删除方法(雾

可以说是非常稳了……

妙!真是妙!


代码如下:

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int val,siz,cnt;
    node *son[2],*fa;
    node(const int &k);
    int dir(){return fa->son[1]==this;}
    void upd(){siz=son[0]->siz+son[1]->siz+cnt;}
}*nil=new node(0),*RT,*flag;
node::node(const int &k)
{
    val=k,siz=cnt=1,son[0]=son[1]=fa=nil;
}
void clear()
{
    nil->siz=nil->cnt=0,RT=nil;
    return;
}
void rotate(node *rt,int d)
{
    node *t=rt->son[d^1];
    rt->son[d^1]=t->son[d];
    if(rt->son[d^1]!=nil)rt->son[d^1]->fa=rt;
    t->son[d]=rt;
    if(rt->fa!=nil)rt->fa->son[rt->dir()]=t;
    t->fa=rt->fa;rt->fa=t;
    rt->upd();t->upd();
    return;
}
void splay(node *rt,node *to)
{
    while(rt->fa!=to)
    {
        if(rt->fa->fa!=to&&rt->dir()==rt->fa->dir())
            rotate(rt->fa->fa,rt->dir()^1);
        rotate(rt->fa,rt->dir()^1);
    }
    if(to==nil)RT=rt;
    return;
}
void add(node *&rt,node *fa,int x)
{
    if(rt==nil)
    {
        rt=new node(x);
        rt->fa=fa;
        flag=rt;
        return;
    }
    if(rt->val==x){rt->cnt++;flag=rt;}
    else if(rt->val>x){add(rt->son[0],rt,x);}
    else {add(rt->son[1],rt,x);}
    rt->upd();
    return;
}
void insert(int x)
{
    add(RT,nil,x);
    splay(flag,nil);
    return;
}
node *lower(node *rt,int x)
{
    if(rt==nil)return nil;
    if(rt->val>=x)return lower(rt->son[0],x);
    else{
        node *t=lower(rt->son[1],x);
        return t==nil?rt:t;
    }
}
node *upper(node *rt,int x)
{
    if(rt==nil)return nil;
    if(rt->val<=x)return upper(rt->son[1],x);
    else
    {
        node *t=upper(rt->son[0],x);
        return t==nil?rt:t;
    }
}
void find(node *rt,int x){
    if(rt==nil)return;
    if(rt->val==x){flag=rt;return;}
    if(rt->val>x)find(rt->son[0],x);
    else find(rt->son[1],x);
    return;
}
void del(int x)
{
    node *l=lower(RT,x),*r=upper(RT,x);
    if(l==nil&&r==nil)
    {
        if(RT->cnt==1)RT=nil;
        else RT->cnt--,RT->siz--;
        return;
    }
    if(l==nil&&r!=nil)
    {
        splay(r,nil);
        if(RT->son[0]->cnt==1)RT->son[0]=nil;
        else RT->son[0]->cnt--,RT->son[0]->siz--;
        RT->upd();
        return;
    }
    if(r==nil)
    {
        splay(l,nil);
        if(RT->son[1]->cnt==1)RT->son[1]=nil;
        else RT->son[1]->cnt--,RT->son[1]->siz--;
        RT->upd();
        return;
    }
    splay(l,nil);
    splay(r,RT);
    node *obj=RT->son[1]->son[0];
    if(obj->cnt==1)RT->son[1]->son[0]=nil;
    else obj->cnt--,obj->siz--;
    RT->son[1]->upd();
    RT->upd();
    return;
}
int rand(int x)
{
    node *rt=RT;int res=1;
    while(rt->val!=x)
    {
        if(rt->val>x)rt=rt->son[0];
        else res=res+rt->son[0]->siz+rt->cnt,rt=rt->son[1];
    }
    res+=rt->son[0]->siz;
    return res;
}
int rand(node *rt,int x)
{
    if(rt->son[0]->siz>=x)return rand(rt->son[0],x);
    if(rt->son[0]->siz+rt->cnt>=x)return rt->val;
    return rand(rt->son[1],x-rt->cnt-rt->son[0]->siz);
}
int read()
{
    int x=0,y=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')y=-y;c=getchar();}
    while(isdigit(c))x=x*10+c-'0',c=getchar();
    return x*y;
}
int main()
{
    clear();
    int n=read();
    while(n--)
    {
        int opt=read(),x=read();
        switch(opt)
        {
            case 1:
            {
                insert(x);
                break;
            }
            case 2:
            {
                del(x);
                break;
            }
            case 3:
            {
                printf("%d\n",rand(x));
                break;
            }
            case 4:
            {
                printf("%d\n",rand(RT,x));
                break;
            }
            case 5:
            {
                printf("%d\n",lower(RT,x)->val);
                break;
            }
            case 6:
            {
                printf("%d\n",upper(RT,x)->val);
                break;
            }
        }
    }
    return 0;
}
/*
10
1 1
4 1
1 3
1 4
*/
SystemC实战:用C++搞芯片建模的5个典型场景(含代码示例) 本文通过五个典型实战场景,详细介绍了如何使用SystemC这一基于C++的硬件建模库进行芯片设计与系统级建模。内容涵盖从基础并发模块构建、事务级总线建模、跨时钟域验证,到与ModelSim协同仿真及多核系统性能探索,并提供了完整的代码示例,帮助软件工程师利用熟悉的C++工具链高效参与硬件架构设计与验证。 阅读详情

相关推荐

解决fetch_california_housing数据集403错误的三种实用方法

本文针对机器学习初学者加载fetch_california_housing数据集时常见的HTTPError 403: Forbidden错误,提供了三种经过实测的解决方案。详细介绍了手动下载与本地替换、修改源码下载路径以及配置网络访问策略的具体步骤,帮助用户根据自身网络环境和开发场景选择最佳方法,确保数据集顺利加载。

weixin_29074295的博客 550

【luogu P3369 【模板】普通平衡树(Treap/SBT)】 题解 pb_ds

我永远都爱STL ! 我爱PB_DS ! #include <iostream> #include <cstdio> #include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/assoc_container.hpp> using namespace __gnu_pbds; typede...

205

CD-HIT的使用

继续我的生信笔记系列。从某网站的附带文献中读到该工具,搜索了一下,发现网上的大佬们都在讲如何用它去冗余,相对官方页面的介绍而言很是片面,于是刚好有聚类的需求的我准备对其全体功能做做实验,学习一下由李伟忠博士在伯纳姆研究所(现为桑福德伯纳姆医学研究所)亚当·戈兹克博士的实验室开发的牛工具。 首先是官方介绍: CD-HIT是一个非常广泛使用的程序,用于蛋白质或核苷酸序列的聚类和比较。最初由李伟忠博士在伯纳姆研究所(现为桑福德伯纳姆医学研究所)亚当·戈兹克博士的实验室开发,CD-HIT速度非常快,可以处理非常

一名学术waste的note pro 1万+

【luogu P3369 普通平衡树(Treap/SBT)】 模板 Splay

题目链接:https://www.luogu.org/problemnew/show/P3369 #include <cstdio> #include <algorithm> #include <iostream> #define ri register #define il inline using namespace std; const int ...

168

基于SHIS凝视型短波红外高光谱相机(900-1700nm)区分不同宝石的差异性和可分性(宝石分选)

SHIS系列凝视型高光谱相机基于液晶可调谐滤波器(LCTF),通过电控LCTF进行连续细分窄波段分光,对每个波段进行高分辨率的二维面阵成像,进行图像处理后,获得完整的高光谱高清图像序列。具有低功耗、小型化、使用方便和易于扩展的优势。其工作波段覆盖400nm至1000nm,能够捕捉宝石在不同波长下的光谱特征,为宝石鉴定提供了新的工具。

wayho的博客 709

3D iToF深度分辨率测量

本文展示了RGB-D传感器在三维测量中的高精度表现。标靶深度图显示其具备清晰、低噪、无干扰的特性,点云数据完整度高且轮廓分明。该技术已成功应用于物流(体积测量误差<1%)、工业(高反光部件装配检测)和农业(果蔬成熟度分级)等领域,验证了其硬件和算法的可靠性,能够满足不同场景下的三维测量需求。

dream it possible 252

P3369 【模板】普通平衡树(Treap/SBT)

treap

sdfzrlt的博客 469

华为OD机试真题 新系统 2026-09-06 Python&JS【仓储货物有序出库】

某仓储中心有一个货物堆放区,货物编号按乱序堆叠存放,只能从顶部取货,管理员需要将货物按编号从小到大取出。

MISAYAONE的博客 114

[洛谷P3369]【模板】普通平衡树(Treap/SBT)

题目大意:给你一些操作: 1.插入一个数; 2.删除一个数; 3.输出x是第几小的数; 4.输出第k小的数是几; 5.输出比x小的最大数; 6.输出比x大的最小数。 要你实现它。 解题思路:平衡树模板题。 用Treap/Splay/替罪羊树/pbds(雾)等均可。 我使用简单的Treap实现。 注意在5和6操作时,必须要搜到叶子才停止,否则会遗漏答案。 这里用指针...

166

DO-297标准详解:IMA系统开发与认证指南

DO-297的前言部分为读者提供了本指南的概述,说明了该标准的编写背景、主要目标、目标受众以及该文件在开发和认证集成模块化航空电子(IMA,Integrated Modular Avionics)系统中的作用。作为现代航空电子架构的重要组成部分,IMA系统大幅度简化了航空电子系统的硬件配置,增加了灵活性并降低了成本。因此,DO-297成为确保IMA系统开发、集成和认证符合适航标准的核心文件。在现代航空领域,系统复杂性逐渐增加,传统上各子系统独立运行的方式已经不适应多任务、多功能的需求。

qq_41854911的博客 1583

【教程4>第6章>第15节】 基于I+jQ复数信号的LS信道估计和均衡实现1——matlab仿真分析,QPSK为例

在基于QPSK调制的通信系统中,LS信道估计和均衡是用于补偿信道失真、提高信号传输质量的重要技术。以下将详细介绍基于I+jQ复数信号的 LS 信道估计和均衡的实现原理与过程。可以看到,通过线性插值之后,QPSK信号的星座图可以模糊的看到四个星座点(图2),通过非线性插值之后,可以清晰的看到QPSK的四个星座点(图3)。可以看到,信道均衡显著提高了通信系统的可靠性和有效性。

FPGA/MATLAB学习教程/源码/项目合作开发 657

Splay各种操作模板大赏

Splay &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;ThinSpace;\ \ \ \ \ \ \ \,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;依然的,只记录模板,不

周道-Althen的博客 395

Bootstrap方法详解——技术与实例

一、Introduction 如果说到Bootstrap你会想到什么?是Twitter推出的那个用于前端开发的开源工具包吗?Unfortunately,本文要讨论的并非是Bootstrap工具包,而是统计学习中一种重采样(Resampling)技术。这种看似简单的方法,对后来的很多技术都产生了深远的影响。机器学习中的Bagging,AdaBoost等方法其实都蕴含了Bootstrap的思想...

白马负金羁 8万+

Splay 模板

雾 /* * by * skip2004 * Splay Tree */ #include <iostream> #include <algorithm> #include <cstring> #include <random> #include <string> #include <cstdio> #...

weixin_30411997的博客 101

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

splay模板基本操作

Splay模板指针实现 splay中序遍历维护原序列下标的顺序,翻转后这个顺序会改变,但是splay中第x个数代表变换后序列中第x个数 这样就可以直接查找变换后的序列 重在代码 文艺平衡树 #include #include #include #include #define INF 0x3f3f3f3f using namespace std; struct node { no

Hunter_HunterL的博客 509

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

静态 Splay Tree 模板

复习一下Splay,没想到一个简单的模板写了一个多小时。。。注:该模板比较短,所以可能会有些难以理解。该结构体包含插入与查询操作。#include<cstdio> #include<cstring> #include<algorithm> using namespace std;const int MAXN = 100010; struct Splay_Tree { int fa[MAXN]

Sunshine_cfbsl 1091

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

splay模板

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 6923  Solved: 2286 [Submit][Status] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账

TUT我好菜啊 766

好用的Splay模板讲解说明

写在前面 #include<cstdio> #include<iostream> using namespace std; const int INF = 0x3f3f3f3f; inline void read(int &w){ w = 0; char c = 0; int f = 1; while(!isdigit(c)){if(c == '-') f = ...

Vanadianfan的博客 283

【code】Splay 模板

#include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; // Splay class Splay{ #define root T[0].son[1] //T[0]为超级根,树根为超级根的右孩子 private: struct Tree{ //一个节点只存储一...

weixin_30505043的博客 73

Splay模板

打LCT的时候发现Splay很不熟, 因此这里贴一下模板 洛谷P3369 https://www.luogu.org/problem/show?pid=3369#sub /* 提一些要注意的点: 1. 注意判断边界, 不要访问到空节点 2. 每一次操作或访问完以后, 记得要splay到root 3. insert操作只要update当前节点和父亲节点即可, ...

dk810510的博客 164

Splay树【模板】

Splay树

hwy0622的博客 210

【bzoj3224】Splay模板

借着这道题贴一下splay的模板

zhaoyh2000的博客 365

splay树 模板

越学越把treap , fhq - Treap和splay记混了,splay树在于其区间翻转等操作 这里先把一些spla树的基本操作模板给一下 可以参考一下这篇文章,关于基本操作的 例题(模板)洛谷3369 对于模板里的“哨兵”,不太理解,但是没了他还过不了。。 这里先留个坑,等弄明白哨兵了之后再来补坑 #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #

CUCUC1的博客 455

Splay树 模板题入门

模板题:HDU 4453 Looploop 以下代码摘自:https://blog.youkuaiyun.com/ck_boss/article/details/48031457 意识到这样的题原来才是模板题之后,我才知道Splay树中,翻转区间是很基本的功能。学到技巧:对区间[L,R]的翻转是用结点L-1和R+1作为一个边界,然后对其子节点标记翻转。很多Splay树的操作都利用了这个边界设置的技巧。 这里有区间增,区间翻转,单点增删,删除子树,求Kth小,splay的旋转结点,这些功能。 #include<cs

TK_wang_的博客 295
上一篇: 【BZOJ】T1101 Zap
下一篇: 【BZOJ】水水知识点
coldhac
博客等级 码龄10年 4粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值