[HNOI2002]营业额统计

http://61.187.179.132/JudgeOnline/problem.php?id=1588

splay,一种功能超级强大的数据结构,且较易实现,核心操作是旋转

求前驱后继

#include <iostream>

#include <cstdio>

using namespace std ; 

const int maxn=100005 ;

const int INF=0xfffffff ;

int son[maxn][2],fa[maxn],key[maxn] ;

int rt,size ;

void link(int x,int y,int k)//将x连到y的k儿子上 0左1右 

{

    fa[x]=y ;

    son[y][k]=x ;

}

void rotate(int x,int k)//k=0 x是y的lson 单旋转 

{

    int y=fa[x] ;

    link(x,fa[y],son[fa[y]][1]==y) ;

    link(son[x][!k],y,k) ;

    link(y,x,!k) ;

}

void splay(int x,int g)

{

    while(fa[x]!=g)

    {

        int y=fa[x],sx=(son[y][1]==x),sy=(son[fa[y]][1]==y) ;

        if(fa[y]==g)

            rotate(x,sx) ;

        else

        {

            if(sx==sy)        //zig-zig || zag-zag

                rotate(y,sx) ;

            else              //zig-zag || zag-zig 

                rotate(x,sx) ;

            rotate(x,sy) ;

        }

    }

    if(!g)rt=x ;

}

void newnode(int y,int &x,int a)

{

    x=++size ;

    fa[x]=y ;key[x]=a ;

    son[x][0]=son[x][1]=0 ;

}

void insert(int a)

{

    int x=rt ;

    while(son[x][key[x]<a])

        x=son[x][key[x]<a] ;

    newnode(x,son[x][key[x]<a],a) ;

    splay(size,0) ;

}

int pre(int a)//前驱 <=a的最大数 

{

    int x=rt,ans=-INF ;

    while(x)

    {

        if(key[x]==a)

            return a ;

        if(key[x]<a)

            ans=max(ans,key[x]) ;

        x=son[x][key[x]<a] ;

    }

    return ans ;

}

int suc(int a)//后继 >=a的最小数 

{

    int x=rt,ans=INF ;

    while(x)

    {

        if(key[x]==a)

            return a ;

        if(key[x]>a)

            ans=min(ans,key[x]) ;

        x=son[x][key[x]<a] ;

    }

    return ans ;

}

int n,a,ans ;

int main()

{

    scanf("%d%d",&n,&a) ;

    ans=a ;

    insert(a) ;

    while(--n)

    {

        if(scanf("%d",&a)==EOF)

            a=0 ;

        ans+=min(a-pre(a),suc(a)-a) ;

        insert(a) ;

    }

    printf("%d\n",ans) ;

    return 0 ;

}
View Code

 

你可能感兴趣的:(统计)