loj10144. 「一本通 4.6 练习 1」宠物收养所

思路:

  treap+简单模拟。

  我只能说:注意取模!!!!

 

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
const int maxn = 80010;
inline void qread(int &x) {
    x = 0;
    register int ch = getchar(), flag = 0;
    while(ch < '0' || ch > '9')        {
        if(ch == '-')    flag = 1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
    if(flag)    x = -x;
}
int rt = 0, tpn, v[maxn], l[maxn], r[maxn], R[maxn], sz[maxn], vn[maxn];
inline void update(int x) {
    sz[x] = sz[l[x]] + sz[r[x]] + vn[x];
}
inline void zig(int &x) {
    int t = l[x];
    l[x] = r[t];
    r[t] = x;
    update(x);
    update(t);
    x = t;
}
inline void zag(int &x) {
    int t = r[x];
    r[x] = l[t];
    l[t] = x;
    update(x);
    update(t);
    x = t;
}
void insert(int &x, int w) {
    if(!x)    {
        x = ++tpn;
        v[x] = w;
        R[x] = rand();
        sz[x] = vn[x] = 1;
        return ;
    }
    if(w < v[x])    insert(l[x], w);
    else if(w > v[x])    insert(r[x], w);
    else            vn[x]++;
    update(x);
    if(l[x] && R[l[x]] < R[x])    zig(x);
    if(r[x] && R[r[x]] < R[x])    zag(x);
}
void pop(int &x, int w) {
    if(w < v[x])    pop(l[x], w);
    else if(w > v[x])    pop(r[x], w);
    else {
        if(vn[x] > 1)    vn[x]--;
        else if(!l[x] || !r[x])    x = l[x] | r[x];
        else if(R[l[x]] < R[r[x]])    zig(x), pop(x, w);
        else                        zag(x), pop(x, w);
    }
    update(x);
}
int ask(int x, int w){
    if(!x)        return -1;
    if(w < v[x])    return ask(l[x], w);
    if(w > v[x])    return ask(r[x], w);
    return     x;
}
int findk(int x, int k){
    if(k >= sz[l[x]] + 1 && k <= sz[l[x]] + vn[x])    return v[x];
    if(k <= sz[l[x]])    return findk(l[x], k);
    return     findk(r[x], k - sz[x] - vn[x]);
}
int findpre(int x, int w){
    int res = -0x3f3f3f3f;
    while(x){
        if(w <= v[x])    x = l[x];
        else            res = v[x], x = r[x];
    }
    return res;
}
int findnxt(int x, int w){
    int res = 0x3f3f3f3f;
    while(x){
        if(w < v[x])    res = v[x], x = l[x];
        else            x = r[x];
    }
    return res;
}
int main(void) {
    srand(11535);
    int n, ans = 0, mode = 0;
    qread(n);
    for(int i=1; i<=n; ++i){
        int x, a;
        qread(x), qread(a);
        if(!sz[rt]) {
            insert(rt, a);
            mode = x;
            continue;
        }
        if(x != mode){
            if(ask(rt, a) == -1){
                int l = findpre(rt, a), r = findnxt(rt, a);
                int minn = min(a - l, r - a), d;
                if(a + minn == r)    d = r;
                if(a - minn == l)    d = l;
                pop(rt, d);
                ans += minn;
                ans %= 1000000;
            }
            else pop(rt, a);
        }
        else
            insert(rt, a);
    }    
    printf("%d\n", ans%1000000);
}

 

转载于:https://www.cnblogs.com/junk-yao-blog/p/9483590.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值