首页 > 其他分享 >Splay

Splay

时间:2024-08-29 14:26:30浏览次数:3  
标签:lazy val int void tot Splay Size

涉及了区间翻转操作,Splay不再是BST;Splay只能保证其中序遍历为当前序列;用lazy标记做,具体见OI-wiki,代码见下

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=100010;
struct Splay
{
    int l,r;
    int cnt,Size;
    int val,lazy;
}a[N];
int tot,n,INF=0x7fffffff,root,fa[N],m;
int New(int val)
{
    a[++tot].val=val;
    a[tot].cnt=a[tot].Size=1;
    a[tot].lazy=0;
    return tot;
}
void update(int p)
{
    a[p].Size=a[a[p].l].Size+a[a[p].r].Size+a[p].cnt;
}
void build()
{
    New(INF),New(-INF);
    a[1].l=2,fa[2]=1;//记录每个点的父亲,这样方便splay操作 
    root=1;
    update(1);
}
void tagrev(int x)
{
    swap(a[x].l,a[x].r);
    a[x].lazy^=1;
}
void pushdown(int x)
{
    if(a[x].lazy)
    {
        tagrev(a[x].l),tagrev(a[x].r);
        a[x].lazy=0;
    }
}
pair<int,int> getval(int p,int rank)//first是答案val,second是得到答案的点,最后会进行splay 
{
    pushdown(p);
    //这里的下传操作不同于线段树,放在最前面
	//估计是因为放在后面会导致splay的时候左右子树是没有交换的左右子树 
	//多下放一层更有正确性 
    if(rank==a[a[p].l].Size+a[p].cnt) return make_pair(a[p].val,p);
    if(rank<=a[a[p].l].Size) return getval(a[p].l,rank);
    return getval(a[p].r,rank-(a[a[p].l].Size+a[p].cnt));
}
int get(int x)//判断x是其父亲的左儿子还是右儿子 
{
    if(a[fa[x]].l==x) return 0;//左儿子 
    else return 1;//右儿子 
}
void zig(int p)//右旋(注意这里没有引用了) 
{
    int q=a[p].l,flag=get(p);
    a[p].l=a[q].r;
    if(a[q].r) fa[a[q].r]=p;
    a[q].r=p,fa[q]=fa[p],fa[p]=q;
    if(fa[q]) 
    {
        if(!flag) a[fa[q]].l=q;
        else a[fa[q]].r=q;
    }
    update(p),update(q);
}
void zag(int p)//左旋 
{
    int q=a[p].r,flag=get(p);
    a[p].r=a[q].l;
    if(a[q].l) fa[a[q].l]=p;
    a[q].l=p,fa[q]=fa[p],fa[p]=q;
    if(fa[q]) 
    {
        if(!flag) a[fa[q]].l=q;
        else a[fa[q]].r=q;
    }
    update(p),update(q);
}
void splay(int x,int goal=0)
{
    if(!goal) root=x;
    for(int f=fa[x];f!=goal;f=fa[x])
    if(fa[f]!=goal)
    {
        bool sonx=get(x),sonf=get(f);
        if(sonx==sonf)//一条链的情况 
        {
            if(!sonx) zig(fa[f]),zig(f);
            else zag(fa[f]),zag(f);
        }
        else//中间有折点的情况 
        {
            if(!sonx) zig(f),zag(fa[x]);
            else zag(f),zig(fa[x]);
        }
    }
    else
    {
        bool sonx=get(x);
        if(!sonx) zig(f);
        else zag(f);
    }
}
int insert(int &p,int f,int val)//插入操作,f为父亲,返回值为splay的点 
{
    if(!p)
    {
        p=New(val);
        fa[p]=f;//这个别忘 
        return p;
    }
    if(val==a[p].val)
    {
        a[p].cnt++,a[p].Size++;
        return p;
    }
    int res;
    if(val<a[p].val) res=insert(a[p].l,p,val);
    else res=insert(a[p].r,p,val);
    update(p);
    return res;
}
void Reverse(int l,int r)
{
    pair<int,int> L=getval(root,l-1),R=getval(root,r+1);
    //注意在geval之后,L到根,R到根的路径上的所有点的左右子树已经交换了 
    splay(L.second),splay(R.second,L.second);
    tagrev(a[a[root].r].l);
}
void print(int x)
{
    if(!x) return;
    pushdown(x);
    print(a[x].l);
    if(a[x].val>=1&&a[x].val<=n) printf("%d ",a[x].val);
    print(a[x].r);
}
int main()
{
    build();
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) splay(insert(root,0,i));
    while(m--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        l++,r++;
        Reverse(l,r);
    }
    print(root);
    return 0;
}

yxc的实现也许可以借鉴一下,没有听过他讲代码的实现,可能比上面的实现更好

标签:lazy,val,int,void,tot,Splay,Size
From: https://www.cnblogs.com/dingxingdi/p/18386606

相关文章

  • [学习笔记] Splay & Treap 平衡树 - 数据结构
    [学习笔记]Splay&Treap平衡树-数据结构Splay树又名伸展树,一种平衡二叉查找树,通过\(\text{Splay}\)操作不断把节点旋到根节点来维护整颗树的平衡。说人话,很玄学的玩意,复杂度是单log级别的。为啥是单log,科学的解释请移步OI-WIKI。不科学的解释就是,通过不断\(\tex......
  • 还在烦恼Cosplay论坛开发?探索PHP+Vue的完美解决方案!
    ......
  • 解锁私人音乐宇宙:SPlayer智能推荐,每日新发现,乐趣无限升级!
    前言在快节奏的工作生活中,你是否经常为了寻找一首好听的歌曲而烦恼?如果有一款音乐播放器,它不仅能让你轻松找到喜欢的歌曲,而且还是开源免费使用;这听起来是不是很吸引人呢?而SPlayer正是这样的一款音乐播放器!无论是在家休闲娱乐,还是在办公室专注工作,都能提供最贴心的音乐享......
  • Docker+Win11:显示Docker中的GUI,解决报错“[Open3D WARNING] GLFW Error: X11: Failed
        在本系列博文中,我将Pytorch部署在Win11为宿主的Docker中,并成功的调用GPU进行了训练。这为我提供了很多便利。    今天在进行3D相关的深度学习研究时我遇到了一些问题:[Open3DWARNING]GLFWError:X11:Failedtoopendisplay:0[Open3DWARNING]Faile......
  • Android开发 - DisplayMetrics 类控制布局图形的缩放显示解析
    DisplayMetrics是什么DisplayMetrics类在Android中用于获取设备的显示属性(像素等)DisplayMetrics的主要属性metrics.density:屏幕密度,用于决定屏幕上每英寸的像素数DisplayMetricsmetrics=newDisplayMetrics();density=metrics.density;常见值:0.75(低密度)、1.0......
  • Android设置DisplayViewport
    //设置DisplayViewportperformTraversalLockedclearViewportsLocked();mViewports.clear();configureDisplayLocked(t,device);populateViewportLocked(viewportType.get(),display.getDisplayIdLocked(),device,info);finalDi......
  • ISO 26262中的失效率计算:IEC TR 62380-Section 17-Displays, solid state lamps
    目录概要1元器件分类2显示器失效率的计算2.1Displays失效率预测模型2.2Base失效率2.3温度循环De-rating系数3固态灯失效率的计算3.1Solidstatelamps失效率预测模型2.2温度循环De-rating系数概要IECTR62380《电子组件、PCBs和设备的可靠性预计通用模型......
  • BossPlayersCTF靶机笔记
    BossPlayersCTF靶机靶机概述这是vulnhub上的一个简单的linux靶机,适合初级渗透测试人员,同时也告诉我们在渗透测试过程中要有耐心,要允许有兔子洞。靶机整体思路:主机端口探测,发现web服务。在web服务中进行信息收集,发现命令注入,反弹shell利用SUID进行提权,拿到rootflag靶机下......
  • 虚拟显卡 display port
    1.虚拟显卡DisplayPort介绍1.基本概念:  DisplayPort是一种高带宽的数字音视频接口,支持高分辨率和高刷新率的显示输出。2.驱动支持:  -Windows操作系统通常会自动识别并安装基本的DisplayPort驱动。  -然而,为了获得最佳性能和全部功能,建议安装显卡制造商......
  • Visionpro二次开发学习笔记7-使用CogToolDisplay控件
    CogToolDisplay控件可显示与视觉工具记录相关的图像,图形和其他状态信息。它使用CogRecord和ICogTool接口将图像和图形连接到CogDisplay。图片清单控件的CogComboBox列出当前记录及其子记录中的图像和图形。您可以单击列表并选择要显示的图像或图形。如果记录层次结构仅包......