权值线段树模版

 pre()函数和getpre()虽类似,但是还有稍许不同,具体用时具体考虑。

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int maxn = 1e5+5;

int T[maxn<<2];
void build(int rt, int l, int r){
    if(l == r) {T[rt] = 0; return ;}
    int mid = l+r >> 1;
    build(ls, l, mid); build(rs, mid+1, r);
    T[rt] = T[ls] + T[rs];
}
void update(int rt, int l, int r, int pos){
    if(l == r) {T[rt] = 1; return ;}
    int mid = l+r >> 1;
    if(pos <= mid) update(ls, l, mid, pos);
    else update(rs, mid+1, r, pos);
    T[rt] = T[ls] + T[rs];
}
int Rank(int rt, int l, int r, int x){ //rank of x (x is existed)
    if(l == r) return 1;
    int mid = l+r >> 1;
    if(x <= mid) return Rank(ls, l, mid, x);
    else return T[ls] + Rank(rs, mid+1, r, x);
}
int query(int rt, int l, int r, int k){ //the number whose rank is k
    if(l == r) return l;
    int mid = l+r >> 1;
    if(k <= T[ls]) return query(ls, l, mid, k);
    else return query(rs, mid+1, r, k-T[ls]);
}
int pre(int rt, int n, int x){ //前驱
    int k = Rank(1, 1, n, x);
    if(k == 1) return -1; //无前驱
    return query(1, 1, n, k-1);
}
int nxt(int rt, int n, int x){ //后继
    int k = Rank(1, 1, n, x);
    if(k == T[1]) return -1; //无后继
    return query(1, 1, n, k+1);
}
//与x的前驱类似,但不相同
int getpre(int rt, int l, int r, int x){ //<=x,且与x的差值最小的数
    if(!T[rt]) return 0;
    if(l == r) return l;
    int mid = l+r >> 1;
    if(x <= mid) return getpre(ls, l, mid, x);
    int t = getpre(rs, mid+1, r, x);
    if(t) return t;
    return getpre(ls, l, mid, x);
}
int getnxt(int rt, int l, int r, int x){ //>=x,且与x的差值最小的数
    if(!T[rt]) return 0;
    if(l == r) return l;
    int mid = l+r >> 1;
    if(x > mid) return getnxt(rs, mid+1, r, x);
    int t = getnxt(ls, l, mid, x);
    if(t) return t;
    return getnxt(rs, mid+1, r, x);
}
int n, a[maxn];
int main()
{
    int l, r, x, op; n = 10;
    while(cin >> op >> x){
        if(op == 1) update(1, 1, n, x);
        else if(op == 2) cout << Rank(1, 1, n, x) << endl;
        else if(op == 3) cout << query(1, 1, n, x) << endl;
        else if(op == 4) cout << pre(1, n, x) << endl;
        else if(op == 5) cout << nxt(1, n, x) << endl;
        else if(op == 6) cout << getpre(1, 1, n, x) << endl;
        else cout << getnxt(1, 1, n, x) << endl;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值