SplayBZOJ1208

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1208

#include <bits/stdc++.h>


using namespace std;
const int N = 1E5 + 7, MOD = 1000000;
int size[N], cnt[N], key[N], ch[N][2], f[N];
int sz, rt;
void clear(int x) {cnt[x]=size[x]=key[x]=ch[x][0]=ch[x][1]=f[x]=0;}
int get(int x) {return x==ch[f[x]][1];}
void pushup(int x)
{
    if(x) {
        size[x] = cnt[x];
        if(ch[x][0]) size[x] += size[ch[x][0]];
        if(ch[x][1]) size[x] += size[ch[x][1]];
    }
}


void rotate(int x, int &k)
{
    int y = f[x], z = f[y], l = get(x), r = !l;
    if(y == k) {
        k = x;
    } else {
        ch[z][get(y)] = x;
    }
    f[x] = z, f[y] = x, f[ch[x][r]] = y;
    ch[y][l] = ch[x][r], ch[x][r] = y;
    pushup(y); pushup(x);
}


void splay(int x, int &k)
{
    while(x != k) {
        int y = f[x];
        if(y != k) rotate( (get(x) == get(y))  ? y : x, k);
        rotate(x, k);
    }
}
void insert(int v)
{
    if(rt == 0) {
        sz ++, ch[sz][0] = ch[sz][1] = f[sz] = 0;
        key[sz] = v, cnt[sz] = size[sz] = 1;
        rt = sz;
        return ;
    }
    int now = rt, fa = 0;
    while(true) {
        if(key[now] == v) {
            cnt[now] ++,  pushup(now), pushup(fa); splay(now, rt);  break;
        }
        fa = now;
        now = ch[now][v > key[now]];
        if(now == 0) {
            sz ++;
            ch[sz][0] = ch[sz][1] = 0; key[sz] = v, cnt[sz] = size[sz] = 1;
            f[sz] = fa; ch[fa][v > key[fa]] = sz;
            pushup(fa);
            splay(sz, rt);
            break;
        }
    }
}


int find(int v) //找到V的排名
{
    int ans = 0, now = rt;
    while(true) {
        if(v < key[now]) {
            now = ch[now][0];
        } else {
            ans += (ch[now][0] ? size[ch[now][0]] : 0);
            if(v == key[now]) {
                splay(now, rt); return ans + 1;
            }
            ans += cnt[now];
            now = ch[now][1];
        }
    }
}


int pre()
{
    int now = ch[rt][0];
    while(ch[now][1]) now = ch[now][1];
    return now;
}
int nxt()
{
    int now = ch[rt][1];
    while(ch[now][0]) now = ch[now][0];
    return now;
}


int findx(int x) //找到排名为X的数
{
    int now = rt;
    while(true) {
        if(ch[now][0] && size[ch[now][0]] >= x) {
            now = ch[now][0];
        } else {
            int tmp = (ch[now][0] ? size[ch[now][0]]:0) + cnt[now];
            if(x <= tmp) return key[now];
            x -= tmp;
            now = ch[now][1];
        }
    }
}
void del(int x)
{
    find(x);
    if(cnt[rt] > 1) {
        cnt[rt] --; return ;
    }
    if(!ch[rt][0] && !ch[rt][1]) {
        clear(rt);
        rt = 0;  return ;
    }
    if(!ch[rt][0]) {
        int oldrt = rt; rt = ch[rt][1]; f[rt] = 0; clear(oldrt); return ;
    } else if(!ch[rt][1]) {
        int oldrt = rt; rt = ch[rt][0]; f[rt] = 0; clear(oldrt); return ;
    }
    int leftBig = pre(), oldrt = rt;
    splay(leftBig, rt);
    f[ch[oldrt][1]] = rt;
    ch[rt][1] = ch[oldrt][1];
    clear(oldrt);
    pushup(rt);
    return ;
}
void add(int &num, int p)
{
    num = (num + p) % MOD;
}
int main()
{
    int n, opt, x, people, pet, num = 0;
    scanf("%d",&n);
    people = pet = 0;
    for(int i = 1;i <= n;i ++) {
        scanf("%d%d",&opt,&x);
        if(!people && !pet) {
            insert(x);
            opt == 1 ? people ++ : pet ++;
        } else if(people > pet) {
            if(opt == 1) insert(x), people ++;
            else {
                people --;
                insert(x);             assert(key[rt] == x);
                if(cnt[rt] > 1) {
                    add(num, 0);
                } else {
                    int tpre,tnxt;
                    tpre = key[pre()];
                    tnxt = key[nxt()];
                    if(tpre == 0) {
                        add(num, abs(x - tnxt));
                        del(tnxt);
                    } else if(tnxt == 0) {
                        add(num, abs(x - tpre));
                        del(tpre);
                    } else {
                        if(tnxt - x >= x - tpre) {
                            add(num, abs(x - tpre));
                            del(tpre);
                        }  else {
                            add(num, abs(x - tnxt));
                            del(tnxt);
                        }
                    }
                }
                del(x);
            }
        } else {
            if(opt == 0) insert(x), pet ++;
            else {
                pet --;
                insert(x);             assert(key[rt] == x);
                if(cnt[rt] > 1) {
                    add(x, 0);
                } else {
                    int tpre,tnxt;
                    tpre = key[pre()];
                    tnxt = key[nxt()];
                    if(tpre == 0) {
                        add(num, abs(x - tnxt));
                        del(tnxt);
                    } else if(tnxt == 0) {
                        add(num, abs(x - tpre));
                        del(tpre);
                    } else {
                        if(tnxt - x >= x - tpre) {
                            add(num, abs(x - tpre));
                            del(tpre);
                        }  else {
                            add(num, abs(x - tnxt));
                            del(tnxt);
                        }
                    }
                }
                del(x);
            }
        }
//        cout << num << endl;
    }
    printf("%d\n", num);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值