首页 > 其他分享 >P1110 (平衡树实现)

P1110 (平衡树实现)

时间:2024-02-27 10:13:02浏览次数:22  
标签:P1110 rt 实现 rx ry long son 平衡 size

难度1

还是比较板的一道题,考的是对平衡树各功能的灵活使用。首先看要求的操作,发现操作三在每次插入时求下前驱后继即可,因为如果答案不是有这个更新的,那么这个答案必定在之前计算过,所以能保证正确性。然后看操作二,发现在每次插入时,有一个原来的差不能再对答案做出贡献,并且有两个新的差进来,考虑维护两颗平衡树分别维护操作二和操作三即可。

同时注意常数带来的问题,比如输入操作的op是个字符串时可考虑只看有区分性的字符,这样会快很多

#include<bits/stdc++.h>
using namespace std;
long long n,T,x,y,a[500005],minn2=1e16;
string op;
vector<long long>v[500005];
namespace treap{
    struct node{
        long long val,rd;//val 值/rd 优先级 
    }p[1000005];
    long long root,size[1000005],son[1000005][2],cnt=0,rx,ry,rz;
    void update(long long rt){
        size[rt]=size[son[rt][0]]+size[son[rt][1]]+1;
    }
    long long add(long long x){
        cnt++;
        size[cnt]=1;
        p[cnt].val=x;
        p[cnt].rd=rand();
        return cnt;
    }
    void split(long long rt,long long key,long long &x,long long &y){
        if(!rt){
            x=y=0;
            return;
        }
        if(p[rt].val<=key){
            x=rt;
            split(son[rt][1],key,son[rt][1],y);
        }
        else{
            y=rt;
            split(son[rt][0],key,x,son[rt][0]);
        }
        update(rt);
    }
    long long merge(long long l,long long r){
        if(!l||!r) return l+r;
        if(p[l].rd<p[r].rd){
            son[l][1]=merge(son[l][1],r);
            update(l);
            return l;
        }else{
            son[r][0]=merge(l,son[r][0]);
            update(r);
            return r;
        }
    }
    long long getrank(long long x,long long k){
        while(true){
            if(k<=size[son[x][0]]){
                x=son[x][0];
            }
            else if(k>size[son[x][0]]+1){
                k-=(size[son[x][0]]+1);
                x=son[x][1];
            }
            else{
                return x;
            }
        }
    }
    void insert(long long x){
        split(root,x,rx,ry);
        root=merge(merge(rx,add(x)),ry);
    }//插入x
    long long getpre(long long x){
        long long gg;
        split(root,x,rx,ry);
        if(!rx) return 1e16;
        gg=getrank(rx,size[rx]);
        root=merge(rx,ry);
        return p[gg].val;
    }//查询x的前驱 
    long long getnxt(long long x){
        long long gg;
        split(root,x-1,rx,ry);
        if(!ry) return 1e16;
        gg=getrank(ry,1);
        root=merge(rx,ry);
        return p[gg].val;
    }//查询x的后继 
}
namespace treap1{
    struct node{
        long long val,rd;//val 值/rd 优先级 
    }p[1000005];
    long long root,size[1000005],son[1000005][2],cnt=0,rx,ry,rz;
    void update(long long rt){
        size[rt]=size[son[rt][0]]+size[son[rt][1]]+1;
    }long long add(long long x){
        cnt++;
        size[cnt]=1;
        p[cnt].val=x;
        p[cnt].rd=rand();
        return cnt;
    }
    void split(long long rt,long long key,long long &x,long long &y){
        if(!rt){
            x=y=0;
            return;
        }if(p[rt].val<=key){
            x=rt;
            split(son[rt][1],key,son[rt][1],y);
        }else{
            y=rt;
            split(son[rt][0],key,x,son[rt][0]);
        }
        update(rt);
    }
    long long merge(long long l,long long r){
        if(!l||!r) return l+r;
        if(p[l].rd<p[r].rd){
            son[l][1]=merge(son[l][1],r);
            update(l);
            return l;
        }else{
            son[r][0]=merge(l,son[r][0]);
            update(r);
            return r;
        }
    }
    long long getrank(long long x,long long k){
        while(true){
            if(k<=size[son[x][0]]){
                x=son[x][0];
            }else if(k>size[son[x][0]]+1){
                k-=(size[son[x][0]]+1);
                x=son[x][1];
            }else{
                return x;
            }
        }
    }
    void insert(long long x){
        split(root,x,rx,ry);
        root=merge(merge(rx,add(x)),ry);
    }//插入x
    void del(long long x){
        split(root,x,rx,rz);
        split(rx,x-1,rx,ry);
        ry=merge(son[ry][0],son[ry][1]);
        root=merge(merge(rx,ry),rz);
    }//删除x
    long long getrnk(long long x){
        return p[getrank(root,x)].val;
    }
}
int main(){
	srand(time(0));
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>T;
	for(long long i=1;i<=n;i++){
		cin>>x;
		a[i]=x;
		v[i].push_back(x);
		if(i>1) treap1::insert(abs(a[i]-a[i-1]));
		minn2=min(minn2,min(abs(x-treap::getpre(x)),abs(x-treap::getnxt(x))));
		treap::insert(x);
	}
	while(T--){
		cin>>op;
		if(op[0]=='I'){
			cin>>x>>y;
			treap1::del(abs(v[x][v[x].size()-1]-v[x+1][0]));
			treap1::insert(abs(v[x][v[x].size()-1]-y));
			treap1::insert(abs(y-v[x+1][0]));
			v[x].push_back(y);
			minn2=min(minn2,min(abs(y-treap::getpre(y)),abs(y-treap::getnxt(y))));
			treap::insert(y);
		}else if(op[4]=='G'){
			cout<<treap1::getrnk(1)<<"\n";
		}else{
			cout<<minn2<<"\n";
		}
	} 
	
	return 0;
}

标签:P1110,rt,实现,rx,ry,long,son,平衡,size
From: https://www.cnblogs.com/wuhupai/p/18036280

相关文章

  • 数据抽取平台pydatax介绍--实现和项目使用
      数据抽取平台pydatax实现过程中,有2个关键点:  1、是否能在python3中调用执行datax任务,自己测试了一下可以,代码如下:  这个str1就是配置的shell文件   try:result=os.popen(str1).read()exceptExceptionase:print(e)2、是否能获取datax执行后......
  • abc305_f (构造实现)
    首先考虑正常的怎么做,就是一遍dfs,是\(O(n)\)的,然而这题在到达每一个点时都要输出它的下一个点才能到达下一个点,同时看到这个\(2n\)觉得不对劲,自然想到走过去走回来,耗2n代码实现还是有点东西的,走过去好搞,但走回来时怎么办呢。我们想到dfs是一个栈,所以在要退出时输出就可以了#inc......
  • JavaScript 实现JSON 对象数组以某个属性进行分组处理
    JavaScript实现JSON对象数组以某个属性进行分组处理要在JavaScript中对JSON对象数组的某个属性进行分组处理,你可以使用一个对象来存储分组后的结果。下面是一个简单的示例,演示了如何对JSON对象数组中的某个属性进行分组处理:假设我们有一个JSON对象数组,每个对象都有ca......
  • 在K8S中,当Pod业务量比较大时候,如何实现水平伸缩和扩容?
    在Kubernetes中,当Pod的业务量比较大时,可以通过水平伸缩(HorizontalPodAutoscaling,HPA)和扩容(Scaling)来实现动态的资源管理。以下是实现水平伸缩和扩容的一些步骤和方法:1.水平伸缩(HorizontalPodAutoscaling,HPA)水平伸缩允许你根据一些指标(如CPU使用率、内存使用率、自定义......
  • [ABC314Ex] Disk and Segments题解(退火实现)
    一到比较水的退火题(虽然也调了3h)题意在平面直角坐标系中,有\(n\)条线段,第\(i\)条的端点是\((a_i,b_i)\)和$(c_i,d_i)$,任意线段不共点。(这里笔者为了方便会默认\(a_i<c_i\))你要在平面上画一个圆,使得任意一条线段都和圆周或圆内部有至少一个公共点,求满足条件的圆的最小......
  • P4666 [BalticOI 2011 Day1] Growing Trees题解(平衡树思想)
    自己第一道不看题解写出来的紫题,庆祝一下(没初始化种子导致调了30min)这是一个fhq-treap的题解思路来源:首先看题目,因为是序列上的问题,不难想到是一道数据结构题。首先看到操作C:对于这种操作,我们可以用平衡树解决,具体方法是,将树split成\(<min,min\lex\lemax,>max\)这......
  • Qt Virtual Keyboard C++集成与实现(QWidget)
    一.设置1.配置所需语言1).通过QtCreator配置打开Qt工程文件,点开左侧 Projects->Build->BuildSteps->qmake->Additionalarguments在 Additionalarguments 增加配置参数:CONFIG+="lang-ar_ARlang-da_DKlang-de_DElang-en_GBlang-es_ESlang-fa_FAlang-fi_FIlang-fr......
  • Qt Virtual Keyboard C++集成与实现(解决模态对话框键盘失效问题)
    一.Qt模态对话框先让我们来看看对话框的几种特性:1.Qt::NonModaThewindowisnotmodalanddoesnotblockinputtootherwindows.2.Qt::WindowModalThewindowismodaltoasinglewindowhierarchyandblocksinputtoitsparentwindow,allgrandparentwin......
  • 基于FPGA的图像双边滤波实现,包括tb测试文件和MATLAB辅助验证
    1.算法运行效果图预览  将FPGA数据导入到matlab对比测试: 2.算法运行软件版本vivado2019.2 matlab2022a 3.算法理论概述         双边滤波是一种非线性滤波方法,它能够在平滑图像的同时保持边缘的锐度。这一特性使得双边滤波在图像处理领域具有广泛的应......
  • 5-2. 滑铲的逻辑和动画的实现
    动画我们需要快速打断滑铲,所以没用结束滑铲动画状态机中,使用了isSlide这个布尔变量NewState->blueSlide0,需要isSlide=true,立即进入blueSlide0->blueSilde1,需要isSlide=true,完整播放一次之后进入当isSlide=false的时候,如果在blueSlide0或blueSlide1,就进......