平衡树入门
BZOJ1588
http://www.lydsy.com/JudgeOnline/problem.php?id=1588
splay维护一下前驱后继
#include<cstdio> #define FOR(i,s,t) for(register int i=s;i<=t;++i) inline int min(int a,int b){ return a<b?a:b; } const int N=100011,inf=(1<<30); int num1,num2; int n,x,ans; namespace Splay{ int sz,rt; int to[N][2],fa[N],num[N]; inline void rotate(int x,int &k){ register int y=fa[x],z=fa[y],l,r; l=(x==to[y][0]?0:1);r=l^1; if(y==k) k=x; else to[z][0]==y?to[z][0]=x:to[z][1]=y; fa[x]=z;fa[y]=x;fa[to[x][r]]=y; to[y][l]=to[x][r];to[x][r]=y; } inline void modify(int x,int &k){ register int y,z; while(x!=k){ y=fa[x];z=fa[y]; if(y!=k)((to[y][0]==x)^(to[z][0]==y))?rotate(x,k):rotate(y,k); rotate(x,k); } } inline void insert(int &k,int x,int father=0){ if(!k){ k=++sz; fa[k]=father; num[k]=x; modify(k,rt); return ; } x<num[k]?insert(to[k][0],x,k):insert(to[k][1],x,k); } inline void ask_before(int k,int x){ if(!k)return; if(num[k]<=x){ num1=num[k]; ask_before(to[k][1],x); } else ask_before(to[k][0],x); } inline void ask_after(int k,int x){ if(!k)return; if(num[k]>=x){ num2=num[k]; ask_after(to[k][0],x); } else ask_after(to[k][1],x); } } using namespace Splay; int main(){ scanf("%d",&n); FOR(i,1,n){ num1=-inf;num2=inf; scanf("%d",&x); ask_after(rt,x); ask_before(rt,x); ans+=(i!=1?min(num2-x,x-num1):x); insert(rt,x); } printf("%d",ans); return 0; }
或者写棵值域线段树冷静一下
#include<cstdio> #include<algorithm> #define FOR(i,s,t) for(register int i=s;i<=t;++i) #define ls k<<1,l,mid #define rs k<<1|1,mid+1,r #define gc getchar() using namespace std; const int N=400011,inf=1e9; int n,pos,ans; int a[N],b[N]; inline int min(int a,int b){ return a<b?a:b; } namespace Segment_Tree{ int tr[N]; inline int query_rank(int x,int k=1,int l=1,int r=40000){ ++tr[k]; if(l==r)return 1; int mid=(l+r)>>1; return x<=mid?query_rank(x,ls):(tr[k<<1]+query_rank(x,rs)); } inline int query_num(int x,int k=1,int l=1,int r=40000){ if(l==r)return l; int mid=(l+r)>>1; return x<=tr[k<<1]?query_num(x,ls):query_num(x-tr[k<<1],rs); } } using namespace Segment_Tree; inline void disc_init(){ sort(b+1,b+b[0]+1); b[0]=unique(b+1,b+b[0]+1)-b-1; FOR(i,1,n) a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b; } int main(){ scanf("%d",&n); b[++b[0]]=-inf,b[++b[0]]=inf; FOR(i,1,n)scanf("%d",a+i),b[++b[0]]=a[i]; disc_init(); query_rank(1),query_rank(b[0]); FOR(i,1,n){ pos=query_rank(a[i]); ans+=(i==1?b[a[i]]:min(b[a[i]]-b[query_num(pos-1)],b[query_num(pos+1)]-b[a[i]])); } printf("%d\n",ans); return 0; }