结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int N, M, rt, cnt; const int MN = 1100010; int ch[MN][2], pre[MN], val[MN]; int newnode ( int x, int p, int v ) {///创建新节点 ch[x][0] = ch[x][1] = 0, pre[x] = p; val[x] = v;///节点上的数值 return x; } void rotate ( int x, int f ) {///把第k位的数转到f下边 ///类似SBT,要把其中一个分支先给父节点 int y = pre[x], z = pre[y]; ch[y][!f] = ch[x][f], pre[ ch[x][f] ] = y; ch[x][f] = y, pre[ y ] = x; pre[x] = z; if ( z ) ch[z][ ch[z][1] == y ] = x; ///如果父节点不是根结点,则要和父节点的父节点连接起来 } int insert ( int &x, int p, int v ) {///插入 if ( x == 0 ) { return newnode ( x = cnt++, p, v ); } else { return insert ( ch[x][ val[x] < v ], x, v ); } } int splay ( int x, int f ) {///Splay调整,将根为r的子树调整为f while ( pre[x] != f ) { int y = pre[x], z = pre[y]; if ( z == f ) rotate ( x, ch[y][0] == x ); else { int f = ( ch[z][1] == y ); if ( ch[y][!f] == x ) { ///两个方向不同,则先左旋再右旋 rotate ( x, f ), rotate ( x, !f ); } else { ///两个方向相同,相同方向连续两次 rotate ( y, !f ), rotate ( x, !f ); } } } if ( f == 0 ) rt = x; ///更新根结点 } int findMax ( int rt ) { return ch[rt][1] == 0 ? rt : findMax ( ch[rt][1] ); } int findMin ( int rt ) { return ch[rt][0] == 0 ? rt : findMin ( ch[rt][0] ); } void print ( int rt ) { if ( rt == 0 ) return; print ( ch[rt][0] ); printf ( "%4d", val[rt] ); print ( ch[rt][1] ); } int main () { // freopen("//media/学习/ACM/input.txt","r",stdin); while ( scanf ( "%d", &N ) == 1 ) { ch[0][1] = ch[0][0] = val[0] = pre[0] = 0;/// cnt = 1, rt = 0; int sum = 0; int mi, ma; for ( int i = 1; i <= N; ++ i ) { if(scanf("%d",&M)==EOF) M=0; int pos = insert ( rt, 0, M ); splay ( pos, 0 ); if ( i>1 && ch[rt][1] == 0 ) mi = -0x5ffffff; else mi = val[ findMin ( ch[rt][1] ) ]; if ( i>1 && ch[rt][0] == 0 ) ma = -0x5ffffff; else ma = val[ findMax ( ch[rt][0] ) ]; if(i==1)sum=abs(M); else sum += min ( abs( M-mi ), abs( M-ma ) ); //cout<<"step "<<i<<" "<<sum<<endl; } //cout<<"result : "; printf ( "%d\n", sum); } return 0; }