KDtree
算法
nth_element(p + l, p + mid, p + r + 1, cmp);
插入的时候类似替罪羊树,\(max(ch[0].size,\ ch[1].size)\ >\ .75size\)就重构
估价函数:
曼哈顿最小:\(max(x[0]\ -\ x,\ 0)\ +\ max(x\ -\ x[1],\ 0)\ +\ max(y[0]\ -\ y,\ 0)\ +\ max(y\ -\ y[1],\ 0)\)
曼哈顿最大:\(max(abs(x\ -\ x[0]),\ abs(x\ -\ x[1]))\ +\ max(abs(y\ -\ y[0]),\ abs(y\ -\ y[1]))\)
欧几里得最小:\(sqr(max(x[0]\ -\ x,\ x\ -\ x[1],\ 0))\ +\ sqr(max(y[0]\ -\ y,\ y\ -\ y[1],\ 0))\)
欧几里得最大:\(max(sqr(x\ -\ x[0]),\ sqr(x\ -\ x[1]))\ +\ max(sqr(y\ -\ y[0]),\ sqr(y\ -\ y[1]))\)
查询的时候先对两个孩子估价,优先递归估价优的那个子树,如果当前估价比答案劣,则return
应用
代码
曼哈顿最近点(无rebuild)
二维单点加区间求和(含rebuild)
二维区间赋值单点查询(无rebuild)
曼哈顿最近点(无rebuild)
#include <bits/stdc++.h>
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif
using namespace std;
const int maxn = 1e6 + 10, oo = 1 << 30;
int cmp_d, n, m, sz, rt, ans;
pair<int, int> pnt[maxn];
struct node {
int d[2], ch[2], a[2][2];
node() { memset(ch, 0, sizeof ch); }
node(pair<int, int> p) { d[0] = a[0][0] = a[1][0] = p.first; d[1] = a[0][1] = a[1][1] = p.second; memset(ch, 0, sizeof ch); }
} pool[maxn];
bool cmp(const pair<int, int> &a, const pair<int, int> &b) { return !cmp_d ? a < b : make_pair(a.second, a.first) < make_pair(b.second, b.first); }
void chkmin(int *a, int *b) { a[0] = min(a[0], b[0]); a[1] = min(a[1], b[1]); return; }
void chkmax(int *a, int *b) { a[0] = max(a[0], b[0]); a[1] = max(a[1], b[1]); return; }
void pull(int u) {
pool[u].a[0][0] = pool[u].a[1][0] = pool[u].d[0]; pool[u].a[0][1] = pool[u].a[1][1] = pool[u].d[1];
if(pool[u].ch[0]) chkmin(pool[u].a[0], pool[pool[u].ch[0]].a[0]), chkmax(pool[u].a[1], pool[pool[u].ch[0]].a[1]);
if(pool[u].ch[1]) chkmin(pool[u].a[0], pool[pool[u].ch[1]].a[0]), chkmax(pool[u].a[1], pool[pool[u].ch[1]].a[1]);
return;
}
void build(int &u, int l, int r, int d = 0) {
if(l > r) return;
int mid = l + r >> 1;
cmp_d = d; nth_element(pnt + l, pnt + mid, pnt + r + 1, cmp); d ^= 1;
pool[u = ++sz] = node(pnt[mid]);
build(pool[u].ch[0], l, mid - 1, d); build(pool[u].ch[1], mid + 1, r, d);
return pull(u);
}
void ins(int &u, int d = 0) {
if(!u) { u = sz; return; }
int &p = pool[u].ch[(pool[sz].d[d] > pool[u].d[d] || pool[sz].d[d] == pool[u].d[d] && pool[sz].d[d ^ 1] > pool[u].d[d ^ 1])];
ins(p, d ^ 1);
return pull(u);
}
int eval(int u, const int &x, const int &y) { return max(pool[u].a[0][0] - x, 0) + max(x - pool[u].a[1][0], 0) + max(pool[u].a[0][1] - y, 0) + max(y - pool[u].a[1][1], 0); }
void q(int u, const int &x, const int &y) {
if(!u) return;
ans = min(ans, abs(x - pool[u].d[0]) + abs(y - pool[u].d[1]));
if(eval(u, x, y) > ans) return;
int d[2] = {oo, oo};
if(pool[u].ch[0]) d[0] = eval(pool[u].ch[0], x, y);
if(pool[u].ch[1]) d[1] = eval(pool[u].ch[1], x, y);
int p = d[1] <= d[0];
if(d[p] < ans) q(pool[u].ch[p], x, y);
if(d[p ^ 1] < ans) q(pool[u].ch[p ^ 1], x, y);
return;
}
int main() {
scanf("%d%d", &n, &m); for (int i = 0; i < n; ++i) scanf("%d%d", &pnt[i].first, &pnt[i].second);
build(rt, 0, n - 1);
while(m--) {
int op, x, y; scanf("%d%d%d", &op, &x, &y);
if(op == 1) pool[++sz] = node(make_pair(x, y)), ins(rt);
else ans = oo, q(rt, x, y), printf("%d\n", ans);
}
return 0;
}
二维单点修改区间求和(含rebuild)
#include <bits/stdc++.h>
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif
using namespace std;
const int maxn = 2e5 + 10;
const double delta = .7;
int n, rt, ru, rp, rd, sz, cmp_d, ans;
vector<int> stk;
pair<pair<int, int>, int> tmp[maxn];
struct node {
int ch[2], d[2], a[2][2], s, v, sz;
node() { memset(ch, 0, sizeof ch); s = v = 0; sz = 1; }
node(int x, int y, int V) {
d[0] = a[0][0] = a[1][0] = x;
d[1] = a[0][1] = a[1][1] = y;
memset(ch, 0, sizeof ch);
v = s = V; sz = 1;
}
} pool[maxn];
void chkmin(int *a, int *b) { for (int i = 0; i < 2; ++i) a[i] = min(a[i], b[i]); return; }
void chkmax(int *a, int *b) { for (int i = 0; i < 2; ++i) a[i] = max(a[i], b[i]); return; }
void pull(int u) {
assert(u);
memcpy(pool[u].a[0], pool[u].d, sizeof(pool[u].a[0]));
memcpy(pool[u].a[1], pool[u].d, sizeof(pool[u].a[1]));
pool[u].s = pool[u].v; pool[u].sz = 1;
for (int v, i = 0; i < 2; ++i) if(v = pool[u].ch[i]) {
chkmin(pool[u].a[0], pool[v].a[0]);
chkmax(pool[u].a[1], pool[v].a[1]);
pool[u].s += pool[v].s; pool[u].sz += pool[v].sz;
}
return;
}
void ins(int &u, int p, int d, int x, int y, int v) {
if(!u) { pool[u = stk.back()] = node(x, y, v); stk.pop_back(); return; }
if(x == pool[u].d[0] && y == pool[u].d[1]) { pool[u].v += v; return pull(u); }
if((d ? make_pair(y, x) : make_pair(x, y)) < make_pair(pool[u].d[d], pool[u].d[d ^ 1])) ins(pool[u].ch[0], u, d ^ 1, x, y, v);
else ins(pool[u].ch[1], u, d ^ 1, x, y, v);
pull(u);
if(delta * pool[u].sz < max(pool[pool[u].ch[0]].sz, pool[pool[u].ch[1]].sz)) ru = u, rp = p, rd = d;
return;
}
void dfs(int u) {
if(!u) return;
dfs(pool[u].ch[0]); dfs(pool[u].ch[1]);
tmp[sz++] = make_pair(make_pair(pool[u].d[0], pool[u].d[1]), pool[u].v);
pool[u] = node(); stk.push_back(u);
return;
}
bool cmp(const pair<pair<int, int>, int> &a, const pair<pair<int, int>, int> &b) {
return cmp_d ? make_pair(a.first.second, a.first.first) < make_pair(b.first.second, b.first.first) : a < b;
}
void build(int &u, int d, int l, int r) {
if(l > r) return;
int mid = l + r >> 1; cmp_d = d; nth_element(tmp + l, tmp + mid, tmp + r + 1, cmp); d ^= 1;
pool[u = stk.back()] = node(tmp[mid].first.first, tmp[mid].first.second, tmp[mid].second); stk.pop_back();
build(pool[u].ch[0], d, l, mid - 1); build(pool[u].ch[1], d, mid + 1, r);
return pull(u);
}
void Q(int u, int x1, int y1, int x2, int y2) {
if(!u) return;
if(x1 <= pool[u].a[0][0] && pool[u].a[1][0] <= x2 && y1 <= pool[u].a[0][1] && pool[u].a[1][1] <= y2) { ans += pool[u].s; return; }
if(pool[u].a[1][0] < x1 || pool[u].a[0][0] > x2 || pool[u].a[1][1] < y1 || pool[u].a[0][1] > y2) return;
if(x1 <= pool[u].d[0] && pool[u].d[0] <= x2 && y1 <= pool[u].d[1] && pool[u].d[1] <= y2) ans += pool[u].v;
Q(pool[u].ch[0], x1, y1, x2, y2); Q(pool[u].ch[1], x1, y1, x2, y2);
return;
}
void out(int u, int tab = 0) {
if(!u) return;
out(pool[u].ch[0], tab + 1);
for (int i = 0; i < tab; ++i) putchar('\t'); printf("%d:\t%d %d\n", u, pool[u].ch[0], pool[u].ch[1]);
out(pool[u].ch[1], tab + 1);
return;
}
int main() {
scanf("%*d");
for (int i = 1; i < maxn; ++i) stk.push_back(i);
for(;;) {
int op; scanf("%d", &op);
if(op == 3) return 0;
if(op == 1) {
int x, y, v; scanf("%d%d%d", &x, &y, &v); x ^= ans; y ^= ans; v ^= ans;
ru = rp = rd = 0; ins(rt, 0, 0, x, y, v);
if(ru) {
sz = 0; dfs(ru);
build(rp ? pool[rp].ch[pool[rp].ch[1] == ru] : rt, rd, 0, sz - 1);
}
}
else {
int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); x1 ^= ans; y1 ^= ans; x2 ^= ans; y2 ^= ans;
ans = 0; Q(rt, x1, y1, x2, y2); printf("%d\n", ans);
}
}
}
二维区间赋值单点查询(无rebuild)
#include <bits/stdc++.h>
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif
using namespace std;
const int maxn = 1e5 + 10, mod = 1e9 + 7;
vector<int> g[maxn];
int n, q, m, dep[maxn], dfn[maxn], End[maxn], sz, rt, cmp_d, ans;
pair<int, int> tmp[maxn];
bool cmp(const pair<int, int> &a, const pair<int, int> &b) {
return cmp_d ? make_pair(a.second, a.first) < make_pair(b.second, b.first) : a < b;
}
struct node {
int d[2], a[2][2], c, ch[2], tag;
node() { memset(ch, 0, sizeof ch); c = 1; tag = 0; }
node(int x, int y) {
c = 1; tag = 0; memset(ch, 0, sizeof ch);
d[0] = a[0][0] = a[1][0] = x;
d[1] = a[0][1] = a[1][1] = y;
}
} pool[maxn];
void dfs(int u) {
dfn[u] = ++m;
for (int v, i = 0; i < g[u].size(); ++i) dep[v = g[u][i]] = dep[u] + 1, dfs(v);
End[u] = m;
return;
}
void chkmin(int *a, int *b) { for (int i = 0; i < 2; ++i) a[i] = min(a[i], b[i]); return; }
void chkmax(int *a, int *b) { for (int i = 0; i < 2; ++i) a[i] = max(a[i], b[i]); return; }
void pull(int u) {
memcpy(pool[u].a[0], pool[u].d, sizeof pool[u].d);
memcpy(pool[u].a[1], pool[u].d, sizeof pool[u].d);
for (int v, i = 0; i < 2; ++i) if(v = pool[u].ch[i]) {
chkmin(pool[u].a[0], pool[v].a[0]);
chkmax(pool[u].a[1], pool[v].a[1]);
}
return;
}
void push(int u) {
int &t = pool[u].tag;
if(t) {
for (int v, i = 0; i < 2; ++i) if(v = pool[u].ch[i]) pool[v].tag = pool[v].c = t;
t = 0;
}
return;
}
void build(int &u, int l, int r, int d = 0) {
if(l > r) return;
int mid = l + r >> 1;
cmp_d = d; nth_element(tmp + l, tmp + mid, tmp + r + 1, cmp);
pool[u = ++sz] = node(tmp[mid].first, tmp[mid].second);
d ^= 1; build(pool[u].ch[0], l, mid - 1, d); build(pool[u].ch[1], mid + 1, r, d);
return pull(u);
}
void M(int u, int x, int y, int z) {
if(!u) return;
if(dep[x] <= pool[u].a[0][0] && pool[u].a[1][0] <= dep[x] + y && dfn[x] <= pool[u].a[0][1] && pool[u].a[1][1] <= End[x]) { pool[u].c = pool[u].tag = z; return; }
if(pool[u].a[0][0] > dep[x] + y || pool[u].a[1][0] < dep[x] || pool[u].a[0][1] > End[x] || pool[u].a[1][1] < dfn[x]) return;
push(u);
if(dep[x] <= pool[u].d[0] && pool[u].d[0] <= dep[x] + y && dfn[x] <= pool[u].d[1] && pool[u].d[1] <= End[x]) pool[u].c = z;
M(pool[u].ch[0], x, y, z); M(pool[u].ch[1], x, y, z);
return;
}
void Q(int u, int x) {
if(!u) return;
if(ans) return;
if(pool[u].a[0][0] > dep[x] || pool[u].a[1][0] < dep[x] || pool[u].a[0][1] > dfn[x] || pool[u].a[1][1] < dfn[x]) return;
push(u);
if(pool[u].d[0] == dep[x] && pool[u].d[1] == dfn[x]) { ans = pool[u].c; return; }
Q(pool[u].ch[0], x); Q(pool[u].ch[1], x);
return;
}
void solve() {
m = 0;
for (int u = 1; u <= n; ++u) g[u].clear();
for (int i = 1; i <= sz; ++i) pool[i] = node(); sz = 0;
scanf("%d%*d%d", &n, &q);
for (int p, i = 2; i <= n; ++i) scanf("%d", &p), g[p].push_back(i);
dep[1] = 0; dfs(1);
for (int u = 1; u <= n; ++u) tmp[u] = make_pair(dep[u], dfn[u]);
rt = 0; build(rt, 1, n);
int res = 0;
for (int i = 1; i <= q; ++i) {
int a, l, c; scanf("%d%d%d", &a, &l, &c);
if(!c) ans = 0, Q(rt, a), res = ((long long) i * ans + res) % mod;
else M(rt, a, l, c);
}
printf("%d\n", res);
return;
}
int main() {
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}