luogu P2234 [HNOI2002]营业额统计

在这里插入图片描述

analysis

splay裸题对吧
只需要一直插入,然后不断的找前驱和后继,然后不断的累加就可以了对吧
确实不难,但是就是调了蒟蒻一晚上
为什么调了我一个晚上呢?因为我太弱了:
我把inf设为1000010,这样子的话inf就会过于靠近正常数据导致了inf和正常数据运算影响了结果,若将inf开到2139062143,就不会有这样的问题了
诶,太弱啦!

code

#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define Fa(id) tree[id].f
#define Lson(id) tree[id].son[0]
#define Rson(id) tree[id].son[1]
template<typename T>void read(T &x){
    x=0;char r=getchar();T neg=1;
    while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
    while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
    x*=neg;
}
int n,root=0,nfp=0;
const int maxn=32767+100;
const int inf=2139062143;
struct node{
    int son[2];
    int f;
    int w;
    int cnt;
    int siz;
}tree[maxn];
inline bool getpos(int id){return ((tree[Fa(id)].son[0]==id)?0:1);}
inline void update(int id){tree[id].siz=tree[Lson(id)].siz+tree[id].cnt+tree[Rson(id)].siz;}
inline void Rotate(int _x){
    int _y=tree[_x].f;
    int _r=tree[_y].f;
    int _pos_y=getpos(_y);
    int _pos_x=getpos(_x);
    int _change_other=tree[_x].son[_pos_x^1];
    tree[_r].son[_pos_y]=_x;
    tree[_x].f=_r;
    tree[_x].son[_pos_x^1]=_y;
    tree[_y].f=_x;
    tree[_y].son[_pos_x]=_change_other;
    tree[_change_other].f=_y;
    update(_y);update(_x);
}
inline void Splay(int id,int to=0){
    int f,ff;
    while(tree[id].f!=to){
        f=Fa(id);ff=Fa(f);
        if(ff!=to){
            if(getpos(f)==getpos(id))Rotate(f);
            else Rotate(id);
        }Rotate(id);
    }
    if(to==0)root=id;
}
inline void Insert(int w){
    int cur=root;int p=0;
    while(cur&&tree[cur].w!=w){
        p=cur;
        cur=tree[cur].son[w>tree[cur].w];
    }
    if(cur)++tree[cur].cnt,Splay(cur);
    else{
        tree[++nfp].w=w;tree[nfp].cnt=tree[nfp].siz=1;
        tree[nfp].f=p;tree[nfp].son[0]=tree[nfp].son[1]=0;
        if(p)tree[p].son[tree[p].w<w]=nfp;
        Splay(nfp);
    }
}
inline void Find(int w){
    int cur=root;
    while(tree[cur].son[tree[cur].w<w]&&tree[cur].w!=w){
        cur=tree[cur].son[tree[cur].w<w];
    }
    Splay(cur);
}
inline int getpre(int w){
    Find(w);
    if(tree[root].w<w)return root;
    int cur=tree[root].son[0];
    while(tree[cur].son[1])
        cur=tree[cur].son[1];
    Splay(cur);
    return cur;
}
inline int getbac(int w){
    Find(w);
    if(tree[root].w>w)return root;
    int cur=tree[root].son[1];
    while(tree[cur].son[0])
        cur=tree[cur].son[0];
    Splay(cur);
    return cur;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("datain.txt","r",stdin);
    //freopen("debugout2.txt","w",stdout);
    #endif // ONLINE_JUDGE
    Insert(inf);
    Insert(-inf);
    read(n);
    int res=0;
    int ai,pre,bac;
    loop(i,1,n){
        read(ai);
        if(i==1)
        	res+=ai,Insert(ai);
        else{
            Find(ai);
            if(tree[root].w!=ai){
                pre=tree[getpre(ai)].w;
                bac=tree[getbac(ai)].w;
                res+=min(abs(bac-ai),abs(pre-ai));
            }Insert(ai);
        }
    }printf("%d",res);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndrewMe8211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值