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;
}
posted @ 2018-07-10 10:02  King_George  阅读(331)  评论(0编辑  收藏  举报