您的位置:首页 > 其它

[HNOI2002]营业额统计 Splay tree

2013-07-14 21:27 295 查看
  Splay tree入门题,学好代码风格,学习HH大牛的,传送门。。

#include <functional>
#include <algorithm>
#include <iostream>
//#include <ext/rope>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
//using namespace __gnu_cxx;
//define
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1.0)
//typedef
typedef long long LL;
typedef unsigned long long ULL;
//const
const int N=100005;
const int INF=0x3f3f3f3f;
const int MOD=100000,STA=8000010;
const LL LNF=1LL<<60;
const double EPS=1e-8;
const double OO=1e15;
const int dx[4]={-1,0,1,0};
const int dy[4]={0,1,0,-1};
const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//Daily Use ...
inline int sign(double x){return (x>EPS)-(x<-EPS);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
//End

int pre
,key
,ch
[2],root,tot;  //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
int n;
//新建一个结点
void addn(int &r,int fa,int k)
{
r=++tot;
pre[r]=fa;
key[r]=k;
ch[r][0]=ch[r][1]=0;  //左右孩子为空
}
//旋转,kind为1为右旋,kind为0为左旋
int Rotate(int x,int kind)
{
int y=pre[x],z=pre[y];
//类似SBT,要把其中一个分支先给父节点
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
//如果父节点不是根结点,则要和父节点的父节点连接起来
if(z)ch[z][ch[z][1]==y]=x;
pre[x]=z;
ch[x][kind]=y;
pre[y]=x;
}
//Splay调整,将根为r的子树调整为goal
int Splay(int r,int goal)
{
int y,kind;
while(pre[r]!=goal){
//父节点即是目标位置,goal为0表示,父节点就是根结点
y=pre[r];
if(pre[y]==goal){
Rotate(r,ch[y][0]==r);
}
else {
kind=ch[pre[y]][0]==y;
//两个方向不同,则先左旋再右旋
if(ch[y][kind]==r){
Rotate(r,!kind);
Rotate(r,kind);
}
//两个方向相同,相同方向连续两次
else {
Rotate(y,kind);
Rotate(r,kind);
}
}
}
//更新根结点
if(goal==0)root=r;
}

int Insert(int k)
{
int r=root;
while(ch[r][k>key[r]]){
//不重复插入
if(key[r]==k){
Splay(r,0);
return 0;
}
r=ch[r][k>key[r]];
}
addn(ch[r][k>key[r]],r,k);
//将新插入的结点更新至根结点
Splay(ch[r][k>key[r]],0);
return 1;
}
//找前驱,即左子树的最右结点
int getpre(int x)
{
if(!ch[x][0])return -INF;
x=ch[x][0];
while(ch[x][1])x=ch[x][1];
return key[x];
}
//找后继,即右子树的最左结点
int getsuf(int x)
{
if(!ch[x][1])return INF;
x=ch[x][1];
while(ch[x][0])x=ch[x][0];
return key[x];
}

int main()
{
//   freopen("in.txt","r",stdin);
int i,a,ans;
while(~scanf("%d",&n))
{
ans=root=tot=0;
for(i=0;i<n;i++){
if(scanf("%d",&a)==EOF)a=0;
if(i==0){
ans+=a;
addn(root,0,a);
}
else {
if(Insert(a)==0)continue;
ans+=Min(a-getpre(root),getsuf(root)-a);
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: