splay

Posted mzh2017

tags:

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

第一次ac的splay纪念(a题量跻身本校前十祭!!!)

代码解决的是求中位数的问题具体见poi2008 block

技术分享图片
#include<bits/stdc++.h>
#define M 1000000
using namespace std;
int size[M],ch[M][2],cnt[M],sum[M],f[M],key[M],sz,root;
int h[M];
void clear(int x){size[x]=ch[x][0]=ch[x][1]=cnt[x]=f[x]=key[x]=key[x]=0;}
int get(int x){return ch[f[x]][1]==x;}
void update(int x){
    if(x){
        size[x]=cnt[x];sum[x]=cnt[x]*key[x];
        if(ch[x][0]) size[x]+=size[ch[x][0]],sum[x]+=sum[ch[x][0]];
        if(ch[x][1]) size[x]+=size[ch[x][1]],sum[x]+=sum[ch[x][1]];
    }
}
void rotate(int x){
    int fa=f[x],gf=f[fa],which=get(x);
    ch[fa][which]=ch[x][which^1];f[ch[fa][which]]=fa;
    f[fa]=x;ch[x][which^1]=fa;
    f[x]=gf;
    if(gf) ch[gf][ch[gf][1]==fa]=x;
    update(fa),update(x);
}
void splay(int x){
    for(int fa;fa=f[x];rotate(x))
    if(f[fa]) rotate(get(x)==get(fa)?fa:x);
    root=x;
}
void insert(int v){
    if(root==0){sz++;ch[sz][0]=ch[sz][1]=f[sz]=0;key[sz]=v;size[sz]=cnt[sz]=1;sum[sz]=v;root=sz;return;}
    int now=root,fa=0;
    while(1){
        if(key[now]==v){
            cnt[now]++;update(now);update(fa);splay(now);break;
        }
        fa=now;
        now=ch[now][key[now]<v];
        if(now==0){
            sz++;
            ch[sz][0]=ch[sz][1]=0;
            key[sz]=v;
            size[sz]=1;cnt[sz]=1;
            f[sz]=fa;ch[fa][key[fa]<v]=sz;
            update(fa);
            splay(sz);
            break;
        }
    }
}
int find(int v){
    int ans=0,now=root;
    while(1){
        if(v<key[now]) now=ch[now][0];
        else{
            ans+=ch[now][0]?size[ch[now][0]]:0;
            if(v==key[now]){splay(now);return ans+1;}
            ans+=cnt[now];
            now=ch[now][1];
        }
    }
}
int findx(int x){
    int now=root;
    while(1){
        if(ch[now][0]&&x<=size[ch[now][0]])
        now=ch[now][0];
        else{
            int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
            if(x<=temp) return now;
            x-=temp;now=ch[now][1];
        }
    }
}
int pre(){
    int now=ch[root][0];
    while(ch[now][1])now=ch[now][1];
    return now;
}
int next(){
    int now=ch[root][1];
    while(ch[now][0]) now=ch[now][0];
    return now;
}
void del(int x){
    int whatever=find(x);
    if(cnt[root]>1){cnt[root]--;return;}
    if(!ch[root][0]&&!ch[root][1]){clear(root);root=0;return;}
    if(!ch[root][0]){
        int oldroot=root;root=ch[root][1];f[root]=0;clear(oldroot);return;
    }
    else if(!ch[root][1]){
        int oldroot=root;root=ch[root][0];f[root]=0;clear(oldroot);return;
    }
    int leftbig=pre(),oldroot=root;
    splay(leftbig);
    f[ch[oldroot][1]]=root;
    ch[root][1]=ch[oldroot][1];
    clear(oldroot);
    update(root);
    return;
}
int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    scanf("%d",&h[i]);
    for(int i=1;i<=k;i++)
    insert(h[i]);
    int p=(k+1)/2;
    int tmp=findx(p);
    splay(tmp);
    long long ans=size[ch[tmp][0]]*key[tmp]-sum[ch[tmp][0]]+sum[ch[tmp][1]]-key[tmp]*size[ch[tmp][1]];
    for(int i=2;i<=n-k+1;i++){
        del(h[i-1]);insert(h[i+k-1]);
        tmp=findx(p);
        splay(tmp);
        ans=min((long long)size[ch[tmp][0]]*key[tmp]-sum[ch[tmp][0]]+sum[ch[tmp][1]]-key[tmp]*size[ch[tmp][1]],ans);
    }
    printf("%lld",ans);
}
哈哈哈

技术分享图片

月光抽出3个月祭

以上是关于splay的主要内容,如果未能解决你的问题,请参考以下文章

UESTC2021暑假前集训(splay树)

SPLAY or SPALY ?

模板Splay

文艺平衡树(splay模板)

bzoj2733 永无乡 splay树的启发式合并

●Splay的一些题