wikioi2573(黑匣子)题解

Description

http://codevs.cn/problem/2573/
题解:
学SBT时因为某些原因半途而废,今天碰到平衡树裸题,就重新练一遍吧。读入add和get数组后,可以模拟出操作序列。仅用到SBT的旋转、maintain、插入和第k大的操作。
代码里大部分是SBT模板。
CODE:

/*
time   :49ms;
memory :1M;
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 50000;
int key[maxn], s[maxn], lc[maxn], rc[maxn];
int n, m, tot, root;
int add[30001], get[30001];
inline void rr(int &t) {
    int k = lc[t];
    lc[t] = rc[k];
    rc[k] = t;
    s[k] = s[t];
    s[t] = s[lc[t]]+s[rc[t]]+1;
    t = k;
}
inline void lr(int &t) {
    int k = rc[t];
    rc[t] = lc[k];
    lc[k] = t;
    s[k] = s[t];
    s[t] = s[lc[t]]+s[rc[t]]+1;
    t = k;
}
void maintain(int &t, bool flag) {
    if(!flag) 
        if(s[lc[lc[t]]] > s[rc[t]]) rr(t);
        else if(s[rc[lc[t]]] > s[rc[t]]) {
            lr(lc[t]);
            rr(t);
        }
        else return;
    else if(s[rc[rc[t]]] > s[lc[t]]) lr(t);
         else if(s[lc[rc[t]]] > s[lc[t]]) {
             rr(rc[t]);
             lr(t);
         }
         else return;
    maintain(lc[t], false);
    maintain(rc[t], true);
    maintain(t, true);
    maintain(t, false);
}
void insert(int &t, int v) {
    if(t == 0) {
        ++tot;
        t = tot;
        key[t] = v;
        s[t] = 1;
        lc[t] = rc[t] = 0;
    }
    else {
        ++s[t];
        if(v < key[t]) insert(lc[t], v);
        else insert(rc[t], v);
        maintain(t, v>=key[t]);
    }
}
int select(int &t, int k) {
    if(k == s[lc[t]]+1) return key[t];
    if(k <= s[lc[t]]) return select(lc[t], k);
    else return select(rc[t], k-1-s[lc[t]]);
}
int main() {
    scanf("%d%d", &m, &n);
    for(int i = 1; i <= m; ++i) scanf("%d", &add[i]);
    for(int i = 1; i <= n; ++i) scanf("%d", &get[i]);
    int lst = 1, now = 1;
    for(int iter = 1; iter <= n; ++iter) {
        for(int i = now; i <= get[iter]; ++i) 
           insert(root, add[i]);
        now = get[iter]+1;
        printf("%d\n", select(root, lst));
        ++lst;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值