BZOJ P1588 [HNOI2002] 营业额统计【Splay】

这道题呢就是一道经典的平衡树板题。

这道题的过程就是插入一个数旋转至根节点,然后查询根节点的前驱后继与它本身做差取最小即可。

参考代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
using namespace std;
const int Max=4e4+5;
const int Mod=1e9+7;
const int Inf=1e9;
int N,Ans,Cnt=1,Root,Fa[Max],Key[Max],Size[Max],CH[Max][2];
inline int Read(){
    int X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}
inline void Write(int X){
    if(X<0)X=-X,putchar('-');
    if(X>9)Write(X/10);
    putchar(X%10+48);
}
void Set(int X,int _Key,int _Size,int _Fa){
    Key[X]=_Key;
    Size[X]=_Size;
    Fa[X]=_Fa;CH[X][0]=CH[X][1]=0;
}
void PushUp(int X){
    Size[X]=Size[CH[X][0]]+Size[CH[X][1]]+1;
}
void Rotate(int X,int P){
    int Y=Fa[X];
    CH[Y][!P]=CH[X][P];
    Fa[CH[X][P]]=Y;Fa[X]=Fa[Y];
    if(Fa[X]){
        CH[Fa[X]][CH[Fa[X]][1]==Y]=X;
    }CH[X][P]=Y;Fa[Y]=X;
    PushUp(Y);PushUp(X);
}
void Splay(int X,int To){
    while(Fa[X]!=To){
        if(Fa[Fa[X]]==To){
            Rotate(X,CH[Fa[X]][0]==X);
        } else {
            int Y=Fa[X],Z=Fa[Y];
            int P=(CH[Z][0]==Y);
            if(CH[Y][P]==X){
                Rotate(X,!P),Rotate(X,P);
            } else {
                Rotate(Y,P),Rotate(X,P);
            }
        }
    }
    if(To==0){
        Root=X;
    }
}
void Insert(int _Key){
    if(!Root){
        Set(Root=Cnt++,_Key,1,0);
    } else {
        int X=Root,Y=0;
        while(X){
            Y=X;X=CH[X][_Key>Key[X]];
        }
        Set(X=Cnt++,_Key,1,Y);
        CH[Y][_Key>Key[Y]]=X;Splay(X,0);
    }
}
int Pre(){
    int X=CH[Root][0];
    if(!X){
        return Inf;
    }
    while(CH[X][1]){
        X=CH[X][1];
    }
    return Key[X];
}
int Suc(){
    int X=CH[Root][1];
    if(!X){
        return Inf;
    } 
    while(CH[X][0]){
        X=CH[X][0];
    }
    return Key[X];
}
int main(){
    int I,J,K;
    N=Read();
    for(I=1;I<=N;I++){
        K=Read();Insert(K);
        int PRE=Pre();
        int SUC=Suc();
        if(I==1){
            Ans=K;
        } else {
            Ans+=min(abs(K-PRE),abs(K-SUC));
        }
    }Write(Ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81063779