【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);
}