1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<ctime>
 5 #include<cstdlib>
 6 #define inf 1000000000
 7 using namespace std;
 8 int t1,t2,n,sz,rt,ans;
 9 int l[50001],r[50001],v[50001],rnd[50001],s[50001];
10 void update(int k){s[k]=s[l[k]]+s[r[k]]+1;}
11 void rturn(int &k)
12 {int t=l[k];l[k]=r[t];r[t]=k;s[t]=s[k];update(k);k=t;}
13 void lturn(int &k)
14 {int t=r[k];r[k]=l[t];l[t]=k;s[t]=s[k];update(k);k=t;}
15 void insert(int &k,int x)
16 {
17     if(!k){k=++sz;v[k]=x;s[k]=1;rnd[k]=rand();return;}
18     s[k]++;
19     if(x<v[k]){insert(l[k],x);if(rnd[l[k]]<rnd[k])rturn(k);}
20     else {insert(r[k],x);if(rnd[r[k]]<rnd[k])lturn(k);}
21 }
22 void ask_before(int k,int x)
23 {
24     if(!k)return;
25     if(x>=v[k]){t1=v[k];ask_before(r[k],x);}
26     else ask_before(l[k],x);
27 }
28 void ask_after(int k,int x)
29 {
30     if(!k)return;
31     if(x<=v[k]){t2=v[k];ask_after(l[k],x);}
32     else ask_after(r[k],x);
33 }
34 int main()
35 {
36     //srand(time(0));
37     scanf("%d",&n);
38     for(int i=1;i<=n;i++)
39     {
40         int x;if(scanf("%d",&x)==EOF)x=0;
41         t1=-inf;t2=inf;
42         ask_before(rt,x);
43         ask_after(rt,x);
44         if(i!=1)ans+=min(x-t1,t2-x);
45         else ans+=x;
46         insert(rt,x);
47     }
48     printf("%d",ans);
49     return 0;
50 }

treap 每次加x点前找出这个点的前驱与后继,两者与x绝对值差取小。

posted on 2016-03-14 22:17  xiyuedong  阅读(182)  评论(0编辑  收藏  举报