您的位置:首页 > 其它

bzoj 1588 splay 模板

2016-08-02 16:03 330 查看
// 每插入一个点求它与树中的点的最小绝对值
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<string>
#define maxi 0x73ffffff
#define maxn 200005
#define LL long long
using namespace std;
struct splayTree{
//关于树的备用的
int son[maxn][2];//0为左儿子,1为右儿子
int fa[maxn];// 该节点的父亲
int rt,tot;//祖宗,节点数量
int siz[maxn];//字数大小本题不需要

inline void up(int i)
{
siz[i] = cnt[i]+siz[son[i][0]]+siz[son[i][1]];
}
inline void Rotate(int x,int flag)//flag 0 左旋,1右旋
{
int y = fa[x]; //y为x父
son[y][!flag] = son[x][flag];
fa[son[x][flag]] = y;//先处理x的儿子

fa[x] = fa[y];
if(fa[y])son[fa[y]][son[fa[y]][1]==y] = x; //再处理y的父亲

fa[y] = x; //再处理 x和y
son[x][flag] = y;
up(y);

}
inline void splay(int x,int goal) //把x旋到goal后面
{
while(fa[x]!=goal)
{
if(fa[fa[x]]==goal)Rotate(x,son[fa[x]][0]==x);//单旋
else{
int fax = fa[x],faxx = fa[fax];
int flag = (son[faxx][0]==fax);
if(son[fax][flag]==x) //双左右或双右左旋
{
Rotate(x,!flag);
Rotate(x,flag);
}
else //左左旋右右旋
{
Rotate(fax,flag);
Rotate(x,flag);
}
}
}
up(x);
if(goal==0)rt = x;
}
inline void visit(int x) //调试GG
{
printf("本点 %d 价值 %d 左二子 %d 右儿子 %d 祖宗 %d\n",x,va[x],son[x][0],son[x][1],rt);
if(son[x][0])visit(son[x][0]);
if(son[x][1])visit(son[x][1]);
}
//以上通用不用修改

void addNode(int val,int far)
{
va[++tot] = val;
son[tot][0] = son[tot][1] = 0;
fa[tot] = far;
son[far][val>=va[far]] = tot;
cnt[tot] = siz[tot] = 1;
}
void init()
{
tot = 0,rt = 1;
addNode(maxi,0);
addNode(-1*maxi,1);
siz[1] = 2;
}
void inser(int pre,int far,int val)//插入啊
{
if(!pre)//插入
{
addNode(val,far);
splay(tot,0);
return ;
}
if(va[pre]==val) //重复计数
{
cnt[pre]++;
up(pre);
splay(pre,0);
return ;
}
if(val>=va[pre])inser(son[pre][1],pre,val);//继续寻找
else inser(son[pre][0],pre,val);
up(pre);
}
void findMax(int &x,int pre,int val)//查询大于等于val的最小值
{
if(!pre)return ;
if(va[pre]>=val)
{
x = va[pre];
findMax(x,son[pre][0],val);
}
else findMax(x,son[pre][1],val);
}
void findMin(int &x,int pre,int val)//查询小于val的最大值
{
if(!pre)return ;
if(va[pre]<val)
{
x = va[pre];
findMin(x,son[pre][1],val);
}
else findMin(x,son[pre][0],val);
}
int va[maxn],cnt[maxn];//va价值 cnt统计这个点的值有多少个
}st;
int main()
{
int n,a;
int ans = 0;
st.init();
scanf("%d",&n);
scanf("%d",&a);
st.inser(st.rt,0,a);
n--;
ans = a;
while(n--)
{
int pre = 0,pre2;
scanf("%d",&a);
st.findMax(pre,st.rt,a);
pre2 = abs(a-pre);
st.findMin(pre,st.rt,a);
pre2 = min(pre2,abs(a-pre));
ans+=pre2;
st.inser(st.rt,0,a);
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: