您的位置:首页 > 其它

BZOJ 1208 宠物收养所 Splay树

2016-07-12 09:32 197 查看
Splay的简单应用,找和一个数最接近的数,例如找和x最接近的数,把x旋转到根,要么是左子树的最大值,要么是右子树的最小值。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long LL;
const int mod = 1000000;
const int maxn = 80010;
const int INF = 999999999;
struct Splay
{
int pre[maxn], ch[maxn][2], sz[maxn];
int root, top;
int val[maxn];

void pushup(int rt)
{
sz[rt] = sz[ch[rt][0]] + sz[ch[rt][1]] + 1;
}
void init()
{
pre[0] = ch[0][0] = ch[0][1] = sz[0] = 0;
root = top = 0;
}

void rotate(int x, int d)
{
int y = pre[x];
ch[y][d^1] = ch[x][d];
pre[ch[x][d]] = y;
if(pre[y])
ch[pre[y]][ch[pre[y]][1] == y] = x;
pre[x] = pre[y];
ch[x][d] = y;
pre[y] = x;
pushup(y);
}

void splay(int x, int goal)
{
while(pre[x] != goal)
{
if(pre[pre[x]] == goal)
{
rotate(x, ch[pre[x]][0] == x);
}
else
{
int y = pre[x], z = pre[y];
int d = (ch[z][0] == y);
if(ch[y][d] == x)
{
rotate(x, d^1);
rotate(x, d);
}
else
{
rotate(y, d);
rotate(x, d);
}
}
}
if(goal == 0)
root = x;
pushup(x);
}

void NewNode(int &x, int f, int c)
{

x = ++top;
ch[x][0] = ch[x][1] = 0;
sz[x] = 1;
pre[x] = f;
val[x] = c;
}

void insert(int k)
{
int x = root;
if(x == 0)
{
NewNode(root, 0, k);
return;
}
while(ch[x][k>val[x]])
x = ch[x][k>val[x]];
NewNode(ch[x][k>val[x]], x, k);
splay(ch[x][k>val[x]], 0);
pushup(x);
}
int get_min(int x)
{
if(!x)
return 0;
while(ch[x][0])
{
x = ch[x][0];
}
return x;
}
int get_max(int x)
{
if(!x)
return 0;
while(ch[x][1])
{
x = ch[x][1];
}
return x;
}
void remove(int x)
{
splay(x, 0);
if(!ch[root][0] && !ch[root][1])
{
root = 0;
return;
}
if(!ch[root][0])
{
root = ch[root][1];
pre[root] = 0;
}
else
{
int m = get_max(ch[root][0]);
splay(m, root);
ch[m][1] = ch[root][1];
pre[ch[root][1]] = m;
root = m;
pre[root] = 0;
pushup(root);
}
}
int find(int x)
{
int rt = root;
while(rt)
{
if(val[rt] == x)
return rt;
rt = ch[rt][x>val[rt]];
}
return rt;
}
LL cal(int x)
{
int rt = find(x);
LL ans = 0;
if(rt != 0)
{
remove(rt);
return 0;
}
insert(x);
int l = ch[root][0], r = ch[root][1];
while(l && ch[l][1])
l = ch[l][1];
while(r && ch[r][0])
r = ch[r][0];
LL d1 = INF, d2 = INF;
if(l)
d1 = x-val[l];
if(r)
d2 = val[r]-x;
if(d1 <= d2)
{
remove(root);
remove(l);
return d1;
}
else
{
remove(root);
remove(r);
return d2;
}
}
}A, B;

int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
LL ans = 0;
A.init();
B.init();
for(int i = 1; i <= n; i++)
{
int x, y;
scanf("%d %d", &x, &y);
if(!x)
{
if(B.sz[B.root] == 0)
A.insert(y);
else
ans += B.cal(y);
}
else
{
if(A.sz[A.root] == 0)
B.insert(y);
else
ans += A.cal(y);
}
ans %= mod;
}
printf("%lld\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: