求波动值(SPLAY树实现)

#include
#include
using namespace std;
const int inf=0x7fffffff;
struct splay_tree{
unsigned long p_size;
struct node{
node l,r,p;
int key;
node(int key):l(NULL),r(NULL),p(NULL),key(key){}
~node(){
if(l)delete l;
if®delete r;
if§delete p;
}
}root;
void right_rotate(node x){
node y=x->l;
if(y){
x->l=y->r;
y->p=x->p;
if(y->r)y->r->p=x;
y->r=x;
}
if(!x->p)root=y;
else if(xx->p->l)x->p->l=y;
else x->p->r=y;
x->p=y;
}
void left_rotate(node *x){
node *y=x->r;
if(y){
x->r=y->l;
y->p=x->p;
if(y->l)y->l->p=x;
y->l=x;
}
if(!x->p)root=y;
else if(x
x->p->r)x->p->r=y;
else x->p->l=y;
x->p=y;
}
void splay(node
x){
while(x->p){
if(!x->p->p){
if(x->p->lx)right_rotate(x->p);
else left_rotate(x->p);
}else if(x->p->l
x&&x->p->p->lx->p){
right_rotate(x->p->p);
right_rotate(x->p);
}else if(x->p->r
x&&x->p->p->rx->p){
left_rotate(x->p->p);
left_rotate(x->p);
}else if(x->p->l
x&&x->p->p->r==x->p){
right_rotate(x->p);
left_rotate(x->p);
}else{
left_rotate(x->p);
right_rotate(x->p);
}
}
}
void replace(node
u,node
v){
if(!u->p)root=v;
else if(u==u->p->l)u->p->l=v;
else u->p->r=v;
if(v)v->p=u->p;
}
node
subtree_minimum(node u){
while(u->l)u=u->l;
return u;
}
node
subtree_maximum(node
u){
while(u->r)u=u->r;
return u;
}
splay_tree():root(NULL),p_size(0){}
void insert(int key){
node
z=root;
nodep=NULL;
while(z){
p=z;
if(z->key<key)z=z->r;
else z=z->l;
}
z=new node(key);
z->p=p;
if(!p)root=z;
else if(p->keykey)p->r=z;
else p->l=z;
splay(z);
p_size++;
}
node find(int key){
node
z=root;
while(z){
if(z->key<key)z=z->r;
else if(keykey)z=z->l;
else return z;
}
return NULL;
}
void erase(int key){
node z=find(key);
if(!z)return;
splay(z);
if(!z->l)replace(z,z->r);
else if(!z->r)replace(z,z->l);
else{
node
y=subtree_minimum(z->r);
if(y->p!=z){
replace(y,y->r);
y->r=z->r;
y->r->p=y;
}
replace(z,y);
y->l=z->l;
y->l->p=y;
}
delete z;
p_size–;
}
int find_prev(int key){
int ans=-inf;
node
x=root;
while(x){
if(x->key==key)return key;
if(x->key<key){
ans=max(ans,x->key);
x=x->r;
}else{
x=x->l;
}

	}
	return ans;
}
int find_next(int key){
	int ans=inf;
	node* x=root;
	while(x){
		if(x->key==key)return key;
		if(x->key>key){
			ans=min(ans,x->key);
			x=x->l;
		}else{
			x=x->r;
		}
	}
	return ans;
}

};
int main(){
splay_tree spt;
int n,sale;
int ans=0;
scanf("%d",&n);
scanf("%d",&sale);
ans=sale;
spt.insert(sale);
for(int i=1;i<n;i++){
scanf("%d",&sale);
int min_fluc=inf;
int prev=spt.find_prev(sale);
if(prev!=-inf)min_fluc=sale-prev;
int next=spt.find_next(sale);
if(next!=inf)min_fluc=min(min_fluc,next-sale);
ans+=min_fluc;
spt.insert(sale);
}
printf("%d\n",ans);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值