[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
",ans) ;
    return 0 ;
}
View Code
原文地址:https://www.cnblogs.com/xiaohongmao/p/3492902.html