社区讨论
KDT 做法求助
P14957【模板】离线静态四维数点参与者 5已保存回复 8
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 8 条
- 当前快照
- 1 份
- 快照标识符
- @mk10skcc
- 此快照首次捕获于
- 2026/01/05 18:30 上个月
- 此快照最后确认于
- 2026/01/08 23:55 上个月
不是 4DT,一维排序一维树状数组两维 KDT。
复杂度分析出来是对的,在程序里算出来理论次数也是对的。但是查询一次访问的实际次数远大于 了,求助一下是怎么回事 /kel
已经排除了重复的点导致复杂度分析错误这个可能性。
CPP#include <bits/stdc++.h>
using namespace std;
typedef array<int, 2> pnt;
const int MAXN = 4e5 + 10;
struct node {
int l, r, w, s; pnt x, tl, tr;
node(pnt x = {}) : l(0), r(0), w(0), s(0), x(x), tl(x), tr(x) {}
} t[MAXN * 19]; int rt[MAXN], cnt, a[MAXN];
inline
void pushup(int p) {
t[p].tl = t[p].tr = t[p].x;
if (t[p].l) {
for (int i = 0; i < 2; i++) t[p].tl[i] = min(t[p].tl[i], t[t[p].l].tl[i]);
for (int i = 0; i < 2; i++) t[p].tr[i] = max(t[p].tr[i], t[t[p].l].tr[i]);
}
if (t[p].r) {
for (int i = 0; i < 2; i++) t[p].tl[i] = min(t[p].tl[i], t[t[p].r].tl[i]);
for (int i = 0; i < 2; i++) t[p].tr[i] = max(t[p].tr[i], t[t[p].r].tr[i]);
}
}
int build(int l, int r, int k = 0) {
if (l > r) return 0; int mid = l + r >> 1;
nth_element(a + l, a + mid, a + r + 1, [k](int i, int j) { return t[i].x[k] < t[j].x[k]; });
int p = a[mid]; t[p].l = build(l, mid - 1, k ^ 1), t[p].r = build(mid + 1, r, k ^ 1);
return pushup(p), p;
}
void add(pnt x, int p) {
if (!p) return ;
if (x[0] < t[p].tl[0] || x[0] > t[p].tr[0]) return ;
if (x[1] < t[p].tl[1] || x[1] > t[p].tr[1]) return ;
t[p].s++;
if (x[0] == t[p].x[0] && x[1] == t[p].x[1]) return t[p].w++, void();
add(x, t[p].l), add(x, t[p].r);
}
int __cnt;
int ask(pnt x, int p) {
__cnt++;
if (!p) return 0;
if (x[0] > t[p].tr[0] || x[1] > t[p].tr[1]) return 0;
if (x[0] <= t[p].tl[0] && x[1] <= t[p].tl[1]) return t[p].s;
if (x[0] > t[p].x[0] || x[1] > t[p].x[1]) return ask(x, t[p].l) + ask(x, t[p].r);
return t[p].w + ask(x, t[p].l) + ask(x, t[p].r);
}
int n, m, b[MAXN];
inline
void tadd(int k, pnt x) {
for (int i = k; i <= n; i += i & -i) add(x, rt[i]);
}
inline
int task(int k, pnt x) {
int res = 0; __cnt = 0;
for (int i = k; i; i &= i - 1) res += ask(x, rt[i]);
assert(__cnt <= 5000); // 就这玩意。n<=2e5 都会 assert 失败。
return res;
}
struct qnode {
int a, b, c, d, id;
qnode(int a = 0, int b = 0, int c = 0, int d = 0, int id = 0) :
a(a), b(b), c(c), d(d), id(id) {}
bool operator < (const qnode &rhs) const { return a == rhs.a ? id < rhs.id : a < rhs.a; }
} q[MAXN << 1];
int ans[MAXN], id[MAXN], rk[MAXN];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1, a, b, c, d; i <= n; i++) {
scanf("%d%d%d%d", &a, &b, &c, &d);
::b[i] = b, q[i] = qnode(a, b, c, d, -i);
}
for (int i = 1, a, b, c, d; i <= m; i++) {
scanf("%d%d%d%d", &a, &b, &c, &d);
q[n + i] = qnode(a, b, c, d, i);
}
sort(b + 1, b + n + 1);
for (int i = 1; i <= n; i++) id[i] = i;
sort(id + 1, id + n + 1, [](int i, int j) { return q[i].b < q[j].b; });
for (int i = 1; i <= n; i++) rk[id[i]] = i;
for (int i = 1; i <= n; i++) {
int len = i & -i;
for (int j = 1; j <= len; j++) {
int k = id[i - j + 1];
t[++cnt] = pnt({ q[k].c, q[k].d }), a[j] = cnt;
}
rt[i] = build(1, len);
}
sort(q + 1, q + n + m + 1);
for (int i = 1; i <= n + m; i++) {
if (q[i].id < 0) tadd(rk[-q[i].id], pnt({ q[i].c, q[i].d }));
else {
int j = upper_bound(::b + 1, ::b + n + 1, q[i].b) - ::b - 1;
ans[q[i].id] = task(j, pnt({ q[i].c, q[i].d }));
}
}
for (int i = 1; i <= m; i++) printf("%d\n", ans[i]);
}
回复
共 8 条回复,欢迎继续交流。
正在加载回复...