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