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绝对值差取小。