普通平衡树(分块版)

Posted 蒟蒻JHY

tags:

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

(题面都一样,就不贴了)

 

今天讲了分块,于是就用分块写了一下这道平衡树模板题hh

离散化之后按权值分块即可,跑得竟然比我平衡树的代码还快hhh

/**************************************************************
    Problem: 3224
    User: JYYHH
    Language: C++
    Result: Accepted
    Time:320 ms
    Memory:3268 kb
****************************************************************/
 
#include<bits/stdc++.h>
#define ll long long
#define maxn 100005
using namespace std;
int n,num[maxn];
int sz,bl[maxn],c[maxn];
int tot[1005],lef[1005],rig[1005];
int opt[maxn],b[maxn],ky,ans,blnum;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",opt+i,b+i);
        if(opt[i]!=4) num[++ky]=b[i];
    }   
    sort(num+1,num+ky+1);
    ky=unique(num+1,num+ky+1)-num-1;
    for(int i=1;i<=n;i++)
        if(opt[i]!=4) b[i]=lower_bound(num+1,num+ky+1,b[i])-num;
     
    sz=sqrt(ky);
    for(int i=1;i<=ky;i++) bl[i]=(i-1)/sz+1;
    blnum=(ky-1)/sz+1;
     
    for(int i=1;i<=n;i++){
        if(opt[i]==1){
            int to=bl[b[i]];
            c[b[i]]++,tot[to]++;
             
            if(c[b[i]]==1){
                if(!lef[to]||b[i]<lef[to]) lef[to]=b[i];
                if(!rig[to]||b[i]>rig[to]) rig[to]=b[i];
            }
        }
        else if(opt[i]==2){
            int to=bl[b[i]];
            c[b[i]]--,tot[to]--;
             
            if(!tot[to]) lef[to]=rig[to]=0;
            else if(!c[b[i]]){
                if(b[i]==lef[to]){
                    for(int j=b[i];bl[j]==to;j++) if(c[j]){
                        lef[to]=j;
                        break;
                    }
                }
                if(b[i]==rig[to]){
                    for(int j=b[i];bl[j]==to;j--) if(c[j]){
                        rig[to]=j;
                        break;
                    }
                }
            }
        }
        else if(opt[i]==3){
            ans=0; int to=bl[b[i]];
            for(int j=b[i]-1;bl[j]==to;j--) ans+=c[j];
            for(int j=to-1;j>0;j--) ans+=tot[j];
            printf("%d\n",ans+1);
        }
        else if(opt[i]==4){
            int tt=0,pos;
            for(int j=1;j<=blnum;j++){
                tt+=tot[j];
                if(tt>=b[i]){
                    tt-=tot[j],pos=j;
                    break;
                }
            }
             
            for(int j=lef[pos];bl[j]==pos;j++){
                tt+=c[j];
                if(tt>=b[i]){
                    printf("%d\n",num[j]);
                    break;
                }
            }
        }
        else if(opt[i]==5){
            int to=bl[b[i]],j;
            for(j=b[i]-1;bl[j]==to;j--) if(c[j]){
                printf("%d\n",num[j]);
                break;
            }
            if(bl[j]!=to){
                for(int j=to-1;j>0;j--) if(rig[j]){
                    printf("%d\n",num[rig[j]]);
                    break;
                }
            }
        }
        else{
            int to=bl[b[i]],j;
            for(j=b[i]+1;bl[j]==to;j++) if(c[j]){
                printf("%d\n",num[j]);
                break;
            }
            if(bl[j]!=to){
                for(int j=to+1;j<=blnum;j++) if(lef[j]){
                    printf("%d\n",num[lef[j]]);
                    break;
                }
            }           
        }
    }
     
    return 0;
}

 

以上是关于普通平衡树(分块版)的主要内容,如果未能解决你的问题,请参考以下文章

luoguP6136 模板普通平衡树(数据加强版)

luoguP6136 模板普通平衡树(数据加强版)

模板 普通平衡树

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

模板普通平衡树

普通平衡树[splay]