【题解】
treap模板题,直接用Treap维护前驱、后继,每次找到更接近当前val的加上就好了。
1 #include<cstdio> 2 #include<algorithm> 3 #define ls (a[u].l) 4 #define rs (a[u].r) 5 #define LL long long 6 using namespace std; 7 const int maxn=200010; 8 int n,k,x,y,z,v,tot,root; 9 struct treap{int l,r,v,rnd,size;}a[maxn]; 10 LL sum=0; 11 inline void read(int &k){ 12 k=0; int f=1; char c=getchar(); 13 while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar(); 14 while(‘0‘<=c&&c<=‘9‘)k=k*10+c-‘0‘,c=getchar(); 15 k*=f; 16 } 17 void newnode(int v){a[++tot]=(treap){0,0,v,rand()+1,1};} 18 void update(int u){a[u].size=a[ls].size+a[rs].size+1;} 19 void split(int u,int k,int &x,int &y){ 20 if(!k){x=0; y=u; return;} 21 if(a[u].size==k){x=u; y=0; return;} 22 if(a[ls].size>=k) split(ls,k,x,ls),y=u; 23 else split(rs,k-a[ls].size-1,rs,y),x=u; 24 update(u); 25 } 26 int merge(int x,int y){ 27 if(!(x*y)) return x+y; 28 if(a[x].rnd>a[y].rnd){ 29 a[y].l=merge(x,a[y].l); update(y); return y; 30 } 31 else{ 32 a[x].r=merge(a[x].r,y); update(x); return x; 33 } 34 } 35 int qrank(int u,int val){ 36 if(!u) return 0; 37 if(a[u].v>=val) return qrank(ls,val); 38 return qrank(rs,val)+a[ls].size+1; 39 } 40 int qval(int u,int k){ 41 if(a[ls].size+1==k) return a[u].v; 42 return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-1); 43 } 44 int main(){ 45 srand(20020705); root=tot=1; a[root].v=2e9; a[root].size=1; 46 read(n); 47 for(int i=1;i<=n;i++){ 48 read(v); 49 if(i<=2) sum+=abs(v-sum); 50 else{ 51 int tmp=qrank(root,v),ans=0X7f7f7f; 52 if(tmp) ans=abs(v-qval(root,tmp)); 53 if(tmp<a[root].size) ans=min(ans,abs(v-qval(root,tmp+1))); 54 sum+=ans; 55 } 56 split(root,qrank(root,v),x,y); 57 newnode(v); root=merge(merge(x,tot),y); 58 } 59 return printf("%lld",sum),0; 60 }