BZOJ1208 宠物收养所

题目链接

题目是中文描述,题意也就不赘述了

实际上我们是动态维护两个集合,对于一个集合,当进入一个新的数的时候,在另一个集合的已有的数中找一个和它最接近的,然后把这个两数取出来,计算绝对值。

数据已经保证每一个集合里面的每一个数都是不一样的,那么这道题就简单了,我们只需要维护两棵平衡树,我选择的是喜闻乐见的Treap……

那么某一个集合进入一个新数的时候,我们只需要询问另外一个集合是否为空,假设不为空,我们就询问一下它的前驱以及后继,找到那个最接近的就行……

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
using namespace std;
const int N = 80010;
const int inf = ~0u >> 1;
const int mod = 1000000;
struct Treap{
    struct node{
        node *ch[2];
        int v, p, sz;
        node(int _v, node *n):
            v(_v){ch[0] = ch[1] = n; p = rand(); sz = 1;}
        void update(){sz = ch[0]->sz + 1 + ch[1]->sz;}
    };
    node *root, *null;
    Treap(){
    }
    void init(){
        null = new node(0, 0); null->sz = 0; null->p = inf;
        null->ch[0] = null->ch[1] = null;
        root = null;
    }
    void rotate(node *&t, bool d){
        node *_t = t->ch[d];
        t->ch[d] = _t->ch[!d];
        _t->ch[!d] = t;
        _t->update();
        t->update();
        t = _t;
    }
    void __insert(node *&t, int val){
        if (t == null){
            t = new node(val, null);
            return;
        }
        bool d = val > t->v;
        __insert(t->ch[d], val);
        if (t->ch[d]->p < t->p) rotate(t, d);
        t->update();
    }
    void __del(node *&t, int val){
        if (t == null) return;
        if (val == t->v){
            bool d = t->ch[1]->p < t->ch[0]->p;
            if (t->ch[d] == null){
                delete t; t = null; return;
            }
            rotate(t, d);
            __del(t->ch[!d], val);
        }else{
            bool d = val > t->v;
            __del(t->ch[d], val);
        }
        t->update();
    }
    void __show(node *t){
        if (t == null) return;
        __show(t->ch[0]);
        printf("%d ", t->v);
        __show(t->ch[1]);
    }
    void insert(int val){
        __insert(root, val);
    }
    void del(int val){
        __del(root, val);
    }
    node *pred(node *t, int val, node *ans){
        if (t == null) return ans;
        if (t->v <= val)
            return pred(t->ch[1], val, t);
        else
            return pred(t->ch[0], val, ans);
    }
    node *succ(node *t, int val, node *ans){
        if (t == null) return ans;
        if (t->v >= val)
            return succ(t->ch[0], val, t);
        else 
            return succ(t->ch[1], val, ans);
    }
    void show(){
        __show(root);
        puts("");
    }
    void __fre(node *t){
        if (t == null) return;
        __fre(t->ch[0]);
        __fre(t->ch[1]);
        delete t;
    }
    void fre(){
        __fre(root);
    }
    int size(){
        return root->sz;
    }
    int solve(int val){
        node *pre, *suc;
        pre = pred(root, val, null);
        suc = succ(root, val, null);
        if (pre != null && suc != null){
            if (abs(val - (pre->v)) > abs(val - (suc->v))){
                del(suc->v);
                return abs(val - (suc->v));
            }else{
                del(pre->v);
                return abs(val - (pre->v));
            }
        }else if (pre == null){
            del(suc->v);
            return abs(val - (suc->v));
        }else if (suc == null){
            del(pre->v);
            return abs(val - (pre->v));
        }
    }
};
int n, op, a;
Treap x, y;
int main(){
    scanf("%d", &n);
    x.init(); y.init();
    int ans = 0;
    for (int i = 1; i <= n; i++){
        scanf("%d%d", &op, &a);
        if (op == 0){
            if (y.size() == 0)
                x.insert(a);
            else
                ans = (ans + y.solve(a)) % mod;
        }else{
            if (x.size() == 0)
                y.insert(a);
            else
                ans = (ans + x.solve(a)) % mod;
        }
    }
    printf("%d\n", ans % mod);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值