【Treap】[HNOI 2002]营业额统计

很简单的基础题目了,就是用Treap重新写了一下练习Treap用的,注意特殊处理有没有前驱和后继的情况,不然要RE

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 2000005

struct Treap{
    Treap *l,*r;
    int fix,key,size;
    Treap(int key_){
        fix = rand();
        l = r = NULL;
        size = 1;
        key = key_;
    }

    inline void updata(){
        size=1+(l?l->size:0)+(r?r->size:0);
    }
}*root;
struct Droot{
    Treap *first, *second;
    Droot(){first = second = NULL;}
};
Droot D_NULL;
inline int Size(Treap *x){return x?x->size:0;}

Treap *Merge(Treap *A,Treap *B){
    if(!A)return B;
    if(!B)return A;
    if(A->fix<B->fix){
        A->r=Merge(A->r,B);
        A->updata();
        return A;
    }else{
        B->l=Merge(A,B->l);
        B->updata();
        return B;
    }
}

Droot Split(Treap *x,int k){
    if(!x)return D_NULL;
    Droot y;
    if(Size(x->l)>=k){
        y=Split(x->l,k);
        x->l=y.second;
        x->updata();
        y.second=x;
    }else{
        y=Split(x->r,k-Size(x->l)-1);
        x->r=y.first;
        x->updata();
        y.first=x;
    }
    return y;
}

int Findkth(int k){
    Droot x=Split(root,k-1);
    Droot y=Split(x.second,1);
    Treap *ans=y.first;
    root=Merge(Merge(x.first,ans),y.second);
    return ans->key;
}

int Getkth(Treap *x,int v){
    if(!x)return 0;
    return v<=x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+1;
}

void Insert(int v){
    int k=Getkth(root,v);
    Droot x=Split(root,k);
    Treap *n=new Treap(v);
    root=Merge(Merge(x.first,n),x.second);
}

void Delete(int k){
    int pos = Getkth(root, k);
    Droot x=Split(root,pos);
    Droot y=Split(x.second,1);
    root=Merge(x.first,y.second);
}

int pre(int k){
    int pos = Getkth(root, k);
    if(pos-1 == Size(root)) return 100000000;
    Droot x = Split(root, pos-1);
    Droot y = Split(x.second, 1);
    Treap *ans = y.first;
    root=Merge(Merge(x.first,ans),y.second);
    return ans->key;
}

int bak(int k){
    int pos = Getkth(root, k+1);
    if(pos == Size(root)) return 100000000;
    Droot x = Split(root, pos);
    Droot y = Split(x.second, 1);
    Treap *ans = y.first;
    root=Merge(Merge(x.first, ans), y.second);
    return ans->key;
}
int M;
int mabs(int r){return r>0?r:-r;}
int main(){
    int now, ans = 1000000, Max, Min;
    scanf("%d",&M);
    if(M) scanf("%d", &ans);
    Insert(ans);
    Max = Min = ans;
    for(int i=1;i<M;i++){
        int td = 1000000000;
        scanf("%d", &now);
        if(now <= Max) td = min(td, mabs(now-bak(now-1)));
        if(now >= Min) td = min(td, mabs(now-pre(now+1)));
        Insert(now);
        Max = max(Max, now);
        Min = min(Min, now);
        ans += td;
    }
    printf("%d\n", ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值