Bootstrap

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

如题,把区间分块,对每个块里的数字排序,然后在块里二分查找,复杂度理论是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;
}


;