平衡树入门

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;
}

  

posted @ 2017-12-26 23:01  Stump  阅读(229)  评论(0编辑  收藏  举报