分块+二分维护,求区间内数字出现的次数

如题,把区间分块,对每个块里的数字排序,然后在块里二分查找,复杂度理论是O(n^1.5*logn)

csy菊苣说把块的大小调整为n*log2(n),复杂度可以降到O(n*sqrt(n*logn))

然后我写了组大随机数据测试了一下,如果分块大小是sqrt(n)用了7.6s,分块大小是n*log2(n)时只用了3.6s!!

效率提升了非常多倍,感觉又是黑科技的节奏,收藏了

const int MX = 1e5 + 5;

struct Data {
    int x, id;
    bool operator<(const Data &P) const {
        return x < P.x;
    }
};

Data A[MX];
int W, n;

void init() {
    W = sqrt(n * log2(n));
    int e = (n - 1) / W + 1;
    for(int i = 1; i <= e; i++) {
        sort(A + (i - 1)*W + 1, A + min(i * W, n) + 1);
    }
}

int solve(int L, int R, int x) {
    int ret = 0, l = (L - 1) / W + 1, r = (R - 1) / W + 1;
    for(int i = (l - 1) * W + 1; i <= min(l * W, n); i++) {
        if(A[i].x == x && A[i].id >= L) ret++;
    }
    if(l == r) return ret;

    for(int i = (r - 1) * W + 1; i <= min(r * W, n); i++) {
        if(A[i].x == x && A[i].id <= R) ret++;
    }

    Data p; p.x = x;
    for(int i = l + 1; i <= r - 1; i++) {
        ret += upper_bound(A + (i - 1) * W + 1, A + i * W + 1, p) - lower_bound(A + (i - 1) * W + 1, A + i * W + 1, p);
    }
    return ret;
}


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值