这题的思路和之前一道“宠物收养所”很像,我们只需要查找每个数的前驱和后继,然后去做差绝对值较小的即可.
1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #include <ctime>
5 #include <cstdlib>
6 using namespace std;
7 int n;
8 struct Treap
9 {
10 Treap *ch[2];
11 int val,size,key;
12 Treap(){val=size=0;key=rand();ch[0]=ch[1]=NULL;}
13 inline void update(){size=1+ch[0]->size+ch[1]->size;}
14 }*null=new Treap(),*root=null;
15 typedef pair<Treap*,Treap*> D;
16 inline Treap* newTreap(int v)
17 {
18 Treap *o=new Treap();
19 o->ch[0]=o->ch[1]=null;
20 o->val=v;o->size=1;
21 return o;
22 }
23 Treap *merge(Treap *a,Treap *b)
24 {
25 if(a==null)return b;
26 if(b==null)return a;
27 if(a->key < b->key)
28 {a->ch[1]=merge(a->ch[1],b);a->update();return a;}
29 else
30 {b->ch[0]=merge(a,b->ch[0]);b->update();return b;}
31 }
32 D split(Treap *o,int k)
33 {
34 if(o==null) return D(null,null);
35 D y;
36 if(o->ch[0]->size >=k)
37 {y=split(o->ch[0],k);o->ch[0]=y.second;o->update();y.second=o;}
38 else
39 {y=split(o->ch[1],k-o->ch[0]->size-1);o->ch[1]=y.first;o->update();y.first=o;}
40 return y;
41 }
42 int getrank(Treap *o,int v)
43 {
44 if(o==null)return 0;
45 return o->val >=v?getrank(o->ch[0],v):getrank(o->ch[1],v)+o->ch[0]->size+1;
46 }
47 inline int getval(int rank)
48 {
49 D x=split(root,rank-1);
50 D y=split(x.second,1);
51 int ret=y.first->val;
52 root=merge(merge(x.first,y.first),y.second);
53 return ret;
54 }
55 inline int query(int val)
56 {
57 int pre=getval(getrank(root,val));
58 int back=getval(getrank(root,val)+1);
59 return min(abs(back-val),abs(pre-val));
60 }
61 inline void insert(int val)
62 {
63 int k=getrank(root,val);
64 D x=split(root,k);
65 Treap *o=newTreap(val);
66 root=merge(merge(x.first,o),x.second);
67 }
68 int main()
69 {
70 scanf("%d",&n);int x,ans=0;
71 while(n--)
72 {
73 scanf("%d",&x);
74 ans+=query(x);
75 insert(x);
76 }
77 printf("%d",ans);
78 }