您的位置:首页 > 其它

[BZOJ1588]营业额统计(平衡树splay)

2016-03-30 13:56 274 查看

题目描述

传送门

题解

平衡树练习。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

const int max_n=40005;
const int INF=2e9;

int n,x;
int f[max_n],ch[max_n][2],key[max_n],cnt[max_n];
int root,sz,last;
int ans;

inline int Abs(int a,int b){
if (a>b) return a-b;
else return b-a;
}

inline int get(int x){
return ch[ f[x] ][1]==x;
}

inline void rotate(int x){
int old=f[x],oldf=f[old],which=get(x);

ch[old][which]=ch[x][which^1];
f[ ch[old][which] ]=old;

ch[x][which^1]=old;
f[old]=x;

f[x]=oldf;
if (oldf)
ch[oldf][ ch[oldf][1]==old ]=x;

}

inline void splay(int x){
for (int fa;fa=f[x];rotate(x))
if (f[fa])
rotate( (get(x)==get(fa)) ?fa:x);
root=x;
}

inline void Insert(int x){
if (root==0){
root=++sz;
f[sz]=ch[sz][0]=ch[sz][1]=0;
cnt[sz]=1;
key[sz]=x;
return;
}

int now=root,fa=0;

while (1){
if (x==key[now]){
cnt[now]++;
splay(now);
break;
}

fa=now;
now=ch[now][ key[now]<x ];

if (now==0){
sz++;

f[sz]=fa;
ch[sz][0]=ch[sz][1]=0;
cnt[sz]=1;
key[sz]=x;

ch[fa][ key[fa]<x ]=sz;
splay(sz);
break;
}
}
}

inline int Find_Pre(int x){
if (cnt[root]>1)
return x;

if (!ch[root][0]) return -INF;
int now=ch[root][0];
while (ch[now][1])
now=ch[now][1];
return key[now];
}

inline int Find_Next(int x){
if (cnt[root]>1)
return x;

if (!ch[root][1]) return -INF;
int now=ch[root][1];
while (ch[now][0])
now=ch[now][0];
return key[now];
}

int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i){
if (scanf("%d",&x)==EOF) x=0;

Insert(x);
int pre=Find_Pre(x);
int next=Find_Next(x);

if (i==1){
ans+=x;
continue;
}

ans+=min( Abs(x,pre) , Abs(x,next) );
}
printf("%d\n",ans);
}


总结

错误记录:

没有前驱或者没有后继的情况,考虑了,但是不够全面。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: