树套树-线段树套平衡树

Posted mysblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树套树-线段树套平衡树相关的知识,希望对你有一定的参考价值。

树套树留坑

线段树套平衡树:

二逼平衡树

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
#include<bitset>
#pragma GCC optimize(2)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
const int N=6000000,inf=2147483647;
int n,m,maxn,a[N+10];
int tot,rt[N+10],sz[N+10],rec[N+10],v[N+10],fa[N+10],ch[N+10][2];
inline int read()

    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    
        if(ch=='-') f=-1;
        ch=getchar();
    
    while(ch>='0'&&ch<='9')
    
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    
    return x*f;

//----------------------Splay--------------------------
inline int ident(int x)return ch[fa[x]][0]==x?0:1;
inline void splay_clear(int x)fa[x]=ch[x][0]=ch[x][1]=sz[x]=rec[x]=v[x]=0;
inline void splay_pushup(int x)sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+rec[x];
inline void rotate(int x)

    int Y=fa[x],R=fa[Y],Yson=ident(x),Rson=ident(Y);
    if(R)ch[R][Rson]=x;
    if(ch[x][Yson^1]) fa[ch[x][Yson^1]]=Y;
    ch[Y][Yson]=ch[x][Yson^1];
    ch[x][Yson^1]=Y;
    fa[Y]=x;
    fa[x]=R;
    splay_pushup(Y),splay_pushup(x);

inline void splay(int &rt,int x,int to)

    to=fa[to];
    while(fa[x]!=to)
    
        int y=fa[x];
        if(fa[y]==to) rotate(x);
        else if(ident(x)==ident(y)) rotate(y),rotate(x);
        else rotate(x),rotate(x);
    
    if(!to) rt=x;

inline void splay_insert(int &rt,int d)

    if(!rt)
    
        rt=++tot;
        v[rt]=d;
        sz[rt]=rec[rt]=1;
        fa[rt]=ch[rt][0]=ch[rt][1]=0;
        return;
    
    int x=rt;
    while(1)
    
        sz[x]++;
        if(v[x]==d)rec[x]++;splay(rt,x,rt);return;
        int nxt=d<v[x]?0:1;
        if(!ch[x][nxt])
        
            ch[x][nxt]=++tot;
            v[tot]=d;
            sz[tot]=rec[tot]=1;
            fa[tot]=x;
            ch[tot][0]=ch[tot][1]=0;
            splay(rt,tot,rt);
            return;
        
        x=ch[x][nxt];
    

inline int splay_rk(int &rt,int d)

    int x=rt,ans=0;
    while(1)
    
        if(!x)return ans;
        if(v[x]==d)ans+=sz[ch[x][0]];splay(rt,x,rt);return ans;
        int nxt=d<v[x]?0:1;
        if(nxt==1) ans+=sz[ch[x][0]]+rec[x];
        x=ch[x][nxt];
    

inline int splay_find(int &rt,int d)

    int x=rt;
    while(1)
    
        if(!x) return 0;
        if(v[x]==d)splay(rt,x,rt);return x;
        int nxt=d<v[x]?0:1;
        x=ch[x][nxt];
    

inline void splay_del(int &rt,int d)

    int x=splay_find(rt,d);
    if(!x) return;
    if(rec[x]>=2)rec[x]--,sz[x]--;return;
    if(!ch[x][0]&&!ch[x][1])rt=0;return;
    if(!ch[x][0])rt=ch[x][1];fa[rt]=0;return;
    if(!ch[x][1])rt=ch[x][0];fa[rt]=0;return;
    int left=ch[x][0];
    while(ch[left][1]) left=ch[left][1];
    splay(rt,left,ch[x][0]);
    fa[ch[x][1]]=left;
    ch[left][1]=ch[x][1];
    fa[left]=0;
    rt=left;
    splay_pushup(left);

inline int splay_lower(int &rt,int d)

    int x=rt,ans=-inf;
    while(x)
    
        if(v[x]<d) ans=max(ans,v[x]);
        int nxt=d<=v[x]?0:1;
        x=ch[x][nxt];
    
    return ans;

inline int splay_upper(int &rt,int d)

    int x=rt,ans=inf;
    while(x)
    
        if(v[x]>d) ans=min(ans,v[x]);
        int nxt=d<v[x]?0:1;
        x=ch[x][nxt];
    
    return ans;

//----------------------Seg_Tree--------------------------
void seg_insert(int k,int l,int r,int x,int d)

    splay_insert(rt[k],d);
    if(l==r) return;
    int mid=(l+r)>>1;
    if(x<=mid) seg_insert(k<<1,l,mid,x,d);
    else seg_insert(k<<1|1,mid+1,r,x,d);

int seg_rk(int k,int l,int r,int ql,int qr,int d)


    if(ql<=l&&r<=qr)return splay_rk(rt[k],d);
    int ans=0,mid=(l+r)>>1;
    if(ql<=mid) ans+=seg_rk(k<<1,l,mid,ql,qr,d);
    if(qr>=mid+1) ans+=seg_rk(k<<1|1,mid+1,r,ql,qr,d);
    return ans;

void seg_change(int k,int l,int r,int x,int d)

    splay_del(rt[k],a[x]),splay_insert(rt[k],d);
    if(l==r)a[x]=d;return;
    int mid=(l+r)>>1;
    if(x<=mid) seg_change(k<<1,l,mid,x,d);
    else seg_change(k<<1|1,mid+1,r,x,d);

int seg_lower(int k,int l,int r,int ql,int qr,int d)

    if(ql<=l&&r<=qr) return splay_lower(rt[k],d);
    int ans=-inf,mid=(l+r)>>1;
    if(ql<=mid) ans=max(ans,seg_lower(k<<1,l,mid,ql,qr,d));
    if(qr>=mid+1) ans=max(ans,seg_lower(k<<1|1,mid+1,r,ql,qr,d));
    return ans;

int seg_upper(int k,int l,int r,int ql,int qr,int d)

    if(ql<=l&&r<=qr) return splay_upper(rt[k],d);
    int ans=inf,mid=(l+r)>>1;
    if(ql<=mid) ans=min(ans,seg_upper(k<<1,l,mid,ql,qr,d));
    if(qr>=mid+1) ans=min(ans,seg_upper(k<<1|1,mid+1,r,ql,qr,d));
    return ans;

inline int seg_kth(int ql,int qr,int k)

    int l=0,r=maxn+1,ans;
    while(l<=r)
    
        int mid=(l+r)>>1;
        if(seg_rk(1,1,n,ql,qr,mid)+1<=k) ans=mid,l=mid+1;
        else r=mid-1;
    
    return ans;

int main()

    n=read(),m=read();
    rep(i,1,n) a[i]=read(),seg_insert(1,1,n,i,a[i]),maxn=max(maxn,a[i]);
    rep(i,1,m)
    
        int opt=read(),x=read(),y=read(),k;
        if(opt==1) k=read(),printf("%d\n",seg_rk(1,1,n,x,y,k)+1);
        if(opt==2) k=read(),printf("%d\n",seg_kth(x,y,k));
        if(opt==3) maxn=max(maxn,y),seg_change(1,1,n,x,y);
        if(opt==4) k=read(),printf("%d\n",seg_lower(1,1,n,x,y,k));
        if(opt==5) k=read(),printf("%d\n",seg_upper(1,1,n,x,y,k));
    
    return 0;

以上是关于树套树-线段树套平衡树的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap

二逼平衡树(树套树)

[TYVJ 1730]二逼平衡树 线段树套平衡树

模板二逼平衡树(树套树)

树套树

「luogu3380」模板二逼平衡树(树套树)