codevs 1296 营业额统计 (splay 点操作)
题目大意
每次加入一个值,并且询问之前加入的数中与该数相差最小的值。
答案输出所有相差值的总和。
解题分析
= =
参考程序
#include <bits/stdc++.h>
using namespace std;
const int INF=2000000000;
class splay_tree
{
private:
struct node
{
int val;
node *l,*r,*f;
node(int _val=0,node *_f=NULL,node *_l=NULL,node *_r=NULL):
val(_val),f(_f),l(_l),r(_r){}
};
node *rt;
void right(node *x,node *&rt)
{
node *y=x->f,*z=y->f;
if (y==rt) rt=x; else if (y==z->l) z->l=x; else z->r=x;
if (x->r) x->r->f=y; y->f=x; x->f=z;
y->l=x->r; x->r=y;
}
void left(node *x,node *&rt)
{
node *y=x->f,*z=y->f;
if (y==rt) rt=x; else if (y==z->l) z->l=x; else z->r=x;
if (x->l) x->l->f=y; y->f=x; x->f=z;
y->r=x->l; x->l=y;
}
void splay(node *x,node *&rt)
{
while (x!=rt)
{
node *y=x->f,*z=y->f;
if (y==rt) if (x==y->l) right(x,rt); else left(x,rt);
else if (y==z->l) if (x==y->l) {right(y,rt);right(x,rt);} else {left(x,rt);right(x,rt);}
else if (x==y->r) {left(y,rt);left(x,rt);} else {right(x,rt);left(x,rt);}
}
}
void insert(int val,node * &x,node *fa)
{
if (x==NULL)
{
x=new node(val,fa);
splay(x,rt);
return;
}
if (val<x->val) insert(val,x->l,x); else insert(val,x->r,x);
}
int search(int val,node *x)
{
int tmp=INF;
while (x!=NULL)
{
if (x->val==val) return 0;
tmp=min(tmp,abs(x->val-val));
if (val<x->val) x=x->l; else x=x->r;
}
return tmp;
}
public:
splay_tree(){rt=NULL;}
void add(int x){insert(x,rt,NULL);}
int find(int x){return search(x,rt);}
};
int main()
{
cin.sync_with_stdio(0);
int n,x;
cin>>n>>x;
long long ans=abs(x);
splay_tree T;
T.add(x);
for (int i=2;i<=n;i++)
{
cin>>x;
ans+=T.find(x);
T.add(x);
}
cout<<ans<<endl;
}