[HNOI2004]宠物收养所【splay】

本文深入探讨了Splay树的基本操作及其实现细节,包括插入、查找、删除等核心功能。通过具体实例,展示了如何利用Splay树解决特定问题,如在动态集合中寻找最接近的值。文章提供了完整的C++代码实现,帮助读者理解和掌握Splay树的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

关于splay的一些讲解


  知道有三种情况,一个是为空的,既没有人也没有宠物的时候,直接加进去即可;另外还有就是现在宠物的数量多的时候,那么就是人去选一个最贴近的;最后一个就是人在排队等待的时候,如果有宠物进来了,就直接宠物去选一个最接近的人即可。

  接下来,用到的就是splay的基本操作,找到最贴近的值,当然最开始的时候别忘记加上两头的最值,为的就是比较的时候不要出意外。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 8e5 + 7;
const int mod = 1000000;
int N, root, tot, pot, op, val;
struct node
{
    int ff, val, cnt, ch[2];
    node() { ff = val = cnt = ch[0] = ch[1] = 0; }
}t[maxN];
void Rotate(int x)
{
    int y = t[x].ff, z = t[y].ff;
    int k = t[y].ch[1] == x;
    t[z].ch[t[z].ch[1] == y] = x;
    t[x].ff = z;
    t[y].ch[k] = t[x].ch[k^1];
    t[t[x].ch[k^1]].ff = y;
    t[x].ch[k^1] = y;
    t[y].ff = x;
}
void Splay(int x, int goal)
{
    while(t[x].ff != goal)
    {
        int y = t[x].ff, z = t[y].ff;
        if(z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? Rotate(x) : Rotate(y);
        Rotate(x);
    }
    if(!goal) root = x;
}
void insert(int x)
{
    int u = root, ff = 0;
    while(u && t[u].val != x)
    {
        ff = u;
        u = t[u].ch[x>t[u].val];
    }
    if(u) t[u].cnt++;
    else
    {
        u = ++tot;
        if(ff) t[ff].ch[x>t[ff].val] = u;
        t[u].ch[0] = t[u].ch[1] = 0;
        t[u].ff = ff;
        t[u].val = x;
        t[u].cnt = 1;
    }
    Splay(u, 0);
}
void Find(int x)
{
    int u = root;
    if(!u) return;
    while(t[u].ch[x>t[u].val] && x != t[u].val) u = t[u].ch[x>t[u].val];
    Splay(u, 0);
}
int Next(int x, int f)
{
    Find(x);
    int u = root;
    if(t[u].val > x && f) return u;
    if(t[u].val < x && !f) return u;
    u = t[u].ch[f];
    while(t[u].ch[f^1]) u = t[u].ch[f^1];
    return u;
}
void Delete(int x)
{
    int last = Next(x, 0), next = Next(x, 1);
    Splay(last, 0); Splay(next, last);
    int del = t[next].ch[0];
    if(t[del].cnt > 1)
    {
        t[del].cnt--;
        Splay(del, 0);
    }
    else t[next].ch[0] = 0;
}
int work(int x)
{
    int last = Next(x, 0), next = Next(x, 1);
    Splay(last, 0); Splay(next, last);
    int del = t[next].ch[0];
    if(del)
    {
        Delete(t[del].val);
        return 0;
    }
    else
    {
        int tmp1 = abs(x - t[last].val), tmp2 = abs(x - t[next].val);
        if(tmp1 <= tmp2)
        {
            Delete(t[last].val);
            return tmp1;
        }
        else
        {
            Delete(t[next].val);
            return tmp2;
        }
    }
}
int main()
{
    ll ans = 0;
    root = tot = pot = 0;
    insert(INF);
    insert(-INF);
    scanf("%d", &N);
    while(N--)
    {
        scanf("%d%d", &op, &val);
        if(pot == 0) insert(val);
        else if(pot > 0)
        {
            if(op == 0) insert(val);
            else { ans += work(val); ans %= mod; }
        }
        else
        {
            if(op == 0) { ans += work(val); ans %= mod; }
            else insert(val);
        }
        pot += (op == 0 ? 1 : -1);
    }
    printf("%lld\n", ans);
    return 0;
}
/*
5
0 2
0 4
1 3
1 2
1 5
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值