带修改的区间第k大

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112

提高代码能力。。。

方法一:

线段树套平衡树,时间:O(m*lgn*lgn*lgn),空间:O(n*lgn)。

<pre name="code" class="cpp">#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int MAXN(50010);

template<typename T>
bool checkmin(T &a, const T &b){
    return b < a? (a = b, true): false;
}
template<typename T>
bool checkmax(T &a, const T &b){
    return b > a? (a = b, true): false;
}

struct RAND{
    int rn[MAXN], si, n;
    void init(int n){
        this->n = n;
        srand(2357);
        for(int i = 0; i < n; ++i) rn[i] = rand();
        si = 0;
    }
    int query(){
        if(si >= n) si -= n;
        return rn[si++];
    }
} ra;

struct NODE1{
    int ke, b, si;
    NODE1 *ch[2];
} *NIL1;

struct POOL1{
    NODE1 pool[MAXN*19], *last;
    void init(){
        last = pool;
    }
    NODE1 *all(int k){
        last->ch[0] = last->ch[1] = NIL1;
        last->ke = k;
        last->b = ra.query();
        last->si = 1;
        return last++;
    }
} pool1;

inline void rep(NODE1 *rt){
    if(rt == NIL1) return;
    rt->si = rt->ch[0]->si+rt->ch[1]->si+1;
}

void rot(NODE1 *&rt, int f){
    NODE1 *s = rt->ch[f];
    rt->ch[f] = s->ch[!f];
    s->ch[!f] = rt;
    rep(rt);
    rep(s);
    rt = s;
}

void Insert(NODE1 *&rt, int k){
    if(rt == NIL1){
        rt = pool1.all(k);
        return;
    }
    int t = (k >= rt->ke);
    Insert(rt->ch[t], k);
    if(rt->ch[t]->b > rt->b) rot(rt, t);
    rep(rt);
}

void Erase(NODE1 *&rt, int k){
    if(rt->ke == k){
        if(rt->ch[0] == NIL1 || rt->ch[1] == NIL1){
            rt = rt->ch[rt->ch[0] == NIL1];
//            rep(rt);
            return;
        }
        int t = rt->ch[0]->b < rt->ch[1]->b;
        rot(rt, t);
   
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值