bzoj3224题解(普通平衡树的线段树解法)

先来orzZKW大神几分钟
题目大意:写一个数据结构,支持平衡树的各种操作
真的要用平衡树吗?不,我们要使用时间效率更好的zkw线段树。《统计的力量》教导我们如下做法:
f[i]记录i出现的频数;
插入:++f[i];
删除:–f[i];
询问x排名:求x-1的前缀和,再加一。因为题目要求最靠前的排名嘛;
查询排名:自顶向下,往左走,左边不够往右。往右一定注意减去左区间的前缀和。(手画线段树才得到的教训啊!)直到走到叶子;
前趋后继的比较朴素的方法:找到叶子后直接向前(后)扫;
数据预处理:500w左右的数组记录线段树,结点数设得比200w大,读入数据后要加上100w+1(c++选手),初始化为0即可。
可以用离散化做得更快。

```
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int T[5000010];
const int dt = 1000001;//变成正数
int n, delta;
void add(int x, int d) {
    for(T[x+=delta] += d, x>>=1; x; x>>=1)
        T[x] = T[x<<1]+T[(x<<1)+1];
}
int query(int t) {
    int s = 1, ans = 0;
    for(s+=delta-1, t+=delta; s^t^1; s>>=1, t>>=1) {
        if(~s&1) ans += T[s^1];
        if(t&1) ans += T[t^1];
    }
    return ans+1;
}
int rank(int x) {
    int iter = 1;
    while(iter < delta) {
        if(x > T[iter<<1]) {
            x -= T[iter<<1];
            iter = (iter<<1)+1;
        }
        else iter<<=1;
    }
    return iter-dt-delta;
}
int pred(int x) {
    x += delta-1;
    while(!T[x]) --x;
    return x-dt-delta;
}
int succ(int x) {
    x += delta+1;
    while(!T[x]) ++x;
    return x-dt-delta;
}
int main() {
    int opt, x;
    freopen("t.txt", "r", stdin);
    scanf("%d", &n);
    delta = (1<<21);
    for(int i = 1; i <= n; ++i) {
        scanf("%d%d", &opt, &x);
        switch(opt) {
            case 1 :add(x+dt, 1); break;
            case 2 :add(x+dt, -1); break;
            case 3 :printf("%d\n", query(x+dt));
                    break;
            case 4 :printf("%d\n", rank(x));
                    break;
            case 5 :printf("%d\n", pred(x+dt));
                    break;
            case 6 :printf("%d\n", succ(x+dt));
                    break;
            default:;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值