robinyqc
2024-07-09 22:02:59
多维数点问题是这样的:
对于两个
k 元组a = (a_0, a_1, \dots, a_{k - 1}) 与b = (b_0, b_1, \dots, b_{k - 1}) ,定义dom(a, b) = \prod\limits_{i = 0}^{k - 1}[a_i \geq b_i] , 也就是若每个a_i 都大于等于b_i (a 偏序b ) 则dom(a, b) = 1 ,否则为0 。给定
n 个k 元组t_0, t_1, \dots, p_{n - 1} ,对于每个i \in [0, n) ,求g(i) = \sum\limits_{j = 0}^{n - 1} dom(t_i, t_j) 。
若
若
若
当
不如来用 bitset 优化暴力的常数。
一个显而易见的暴力做法是直接枚举
一个性质是,
那么可以交换枚举顺序,先枚举维数(元组下标)
实际上
总复杂度
可以发现上面这个问题可以用 bitset 压位优化。开一个二维数组 bitset<N> b[N]
。
考虑上面暴力的转移式子
从
时间复杂度
此时空间并不是很优秀,很有可能开不下。此时可以用一个常见的手段:分组跑。
将
由于
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <cmath>
using namespace std;
using i32 = int;
using i64 = long long;
using u32 = unsigned int;
using u64 = unsigned long long;
template<typename T> using vec = vector<T>;
signed main()
{
u32 k, n;
cin >> k >> n;
// p[k][i].first = p[i][k], p[k][i].second = l[i]
vec<vec<pair<u32, u32>>> p(k, vec<pair<u32, u32>>(n));
for (u32 i = 0; i < n; i++) {
for (u32 d = 0; d < k; d++) {
cin >> p[d][i].first;
p[d][i].second = i;
}
}
for (u32 d = 0; d < k; d++) sort(p[d].begin(), p[d].end());
vec<u32> ans(n);
// S mentioned above.
// Note that larger bs, less time cost, but more space cost.
const u32 bs = ceil(sqrt(n)) * 16;
for (u32 i = 0; i * bs < n; i++) {
u32 l = i * bs, r = min(n, i * bs + bs);
// '80000' means n is no more than 80000.
vec<bitset<80000>> b(r - l);
for (auto &c: b) c.set();
for (u32 d = 0; d < k; d++) {
bitset<80000> s; ///< relationship array mentioned above
for (u32 j = 0, it = 0; j < n; j++) {
auto [v, q] = p[d][j];
while (it < n && p[d][it].first <= v) s.set(p[d][it++].second);
if (l <= q && q < r) b[q - l] &= s;
}
}
for (u32 j = l; j < r; j++) ans[j] = b[j - l].count();
}
for (u32 i = 0; i < n; i++) cout << ans[i] << '\n';
return 0;
}
相关题目:CF1826E。
其实在 CF 上我写了一份英文版的,欢迎来看。(求 upvote QwQ)