平方分割和分桶法
平方分割就是在维护一个数列上的某些信息时,通常将 O ( n ) O(\sqrt{n}) O(n)的元素分在一个桶内,分别维护每个桶内的信息。
这样当我们查询某些信息时就可以分为桶内查询和逐个查询,由于桶的数目为 O ( n ) O(\sqrt{n}) O(n)级别的,逐个查询的复杂度也是 O ( n ) O(\sqrt{n}) O(n)级别的,于是就将 O ( n 2 ) O(n^2) O(n2)降为了 O ( n n ) O(n\sqrt{n}) O(nn)。
const int B = 1000;
int n, m, a[N], num[N];
vector<int> bucket[N / B];
void solve()
{
rep(i, n) num[i] = a[i], bucket[i / B].push_back(a[i]); // 一些预处理
sort(num, num + n);
rep(i, n / B) sort(bucket[i].begin(), bucket[i].end());
while (m --){
int l, r, k; scanf("%d%d%d", &l, &r, &k), l --; // 左闭右开 [l, r) !!!
int lb = 0, rb = n;
while (rb - lb > 1){ // do something
int mid = (lb + rb) >> 1;
int x = num[mid], c = 0;
int tl = l, tr = r;
for (; tl < min(tr, (tl + B - 1) / B * B); tl ++) if (a[tl] < x) c ++;
for (; tr > max(tl, tr / B * B); tr --) if (a[tr - 1] < x) c ++; // 逐个查询
for (; tl < tr; tl += B){ // 桶内查询
c += lower_bound(bucket[tl / B].begin(), bucket[tl / B].end(), x) - bucket[tl / B].begin();
}
if (c < k) lb = mid;
else rb = mid;
}
printf("%d\n", num[lb]);
}
return 0;
}