【BZOJ2683】简单题

【题目链接】

【三倍经验链接】

【思路要点】

  • KDTree+替罪羊树式重构即可。
  • 时间复杂度\(O(N\sqrt{N})\)。

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN	200005
#define ALPHA	0.65
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
struct point {int x, y, v; };
bool operator == (point a, point b) {
	return a.x == b.x && a.y == b.y;
}
void operator += (point &a, point b) {
	a.v += b.v;
}
int cmptype; //Type0 : x first, y second; type1 : y first, x second.
bool operator < (point a, point b) {
	if (cmptype) return (a.y < b.y) || (a.y == b.y && a.x < b.x);
	else return (a.x < b.x) || (a.x == b.x && a.y < b.y);
}
struct KD_Tree {
	struct node {
		int lc, rc;
		int sum, size;
		int Lx, Ly, Rx, Ry;
		point info;
	} a[MAXN];
	int root, mem[MAXN], top, len;
	point tmp[MAXN];
	int reroot, retype;
	int ans, qlx, qly, qrx, qry;
	void init(int n) {
		for (int i = 1; i <= n; i++)
			mem[i] = i;
		top = 1;
	}
	int new_node() {
		int tmp = mem[top++];
		a[tmp].info = (point) {0, 0, 0};
		a[tmp].lc = a[tmp].rc = a[tmp].sum = 0;
		return tmp;
	}
	void update(int root) {
		a[root].size = 1;
		a[root].sum = a[root].info.v;
		a[root].Lx = a[root].Rx = a[root].info.x;
		a[root].Ly = a[root].Ry = a[root].info.y;
		if (a[root].lc) {
			int tmp = a[root].lc;
			a[root].size += a[tmp].size;
			a[root].sum += a[tmp].sum;
			a[root].Lx = a[root].Lx < a[tmp].Lx ? a[root].Lx : a[tmp].Lx;
			a[root].Ly = a[root].Ly < a[tmp].Ly ? a[root].Ly : a[tmp].Ly;
			a[root].Rx = a[root].Rx > a[tmp].Rx ? a[root].Rx : a[tmp].Rx;
			a[root].Ry = a[root].Ry > a[tmp].Ry ? a[root].Ry : a[tmp].Ry;
		}
		if (a[root].rc) {
			int tmp = a[root].rc;
			a[root].size += a[tmp].size;
			a[root].sum += a[tmp].sum;
			a[root].Lx = a[root].Lx < a[tmp].Lx ? a[root].Lx : a[tmp].Lx;
			a[root].Ly = a[root].Ly < a[tmp].Ly ? a[root].Ly : a[tmp].Ly;
			a[root].Rx = a[root].Rx > a[tmp].Rx ? a[root].Rx : a[tmp].Rx;
			a[root].Ry = a[root].Ry > a[tmp].Ry ? a[root].Ry : a[tmp].Ry;
		}
	}
	bool unbalance(int root) {
		return max(a[a[root].lc].size, a[a[root].rc].size) > a[root].size * ALPHA + 1;
	}
	void recycle(int root) {
		mem[--top] = root;
	}
	void dfs(int root) {
		if (root != reroot) recycle(root);
		if (a[root].lc) dfs(a[root].lc);
		tmp[++len] = a[root].info;
		if (a[root].rc) dfs(a[root].rc);
	}
	void rebuild(int root, int l, int r, int type) {
		int mid = (l + r) / 2;
		cmptype = type;
		nth_element(tmp + l, tmp + mid, tmp + r + 1);
		a[root].info = tmp[mid];
		if (l < mid) {
			a[root].lc = new_node();
			rebuild(a[root].lc, l, mid - 1, type ^ 1);
		}
		if (mid < r) {
			a[root].rc = new_node();
			rebuild(a[root].rc, mid + 1, r, type ^ 1);
		}
		update(root);
	}
	void rebuild() {
		len = 0;
		dfs(reroot);
		a[reroot].lc = a[reroot].rc = 0;
		rebuild(reroot, 1, len, retype);
	}
	void insert(int &root, point value, int type) {
		if (root == 0) {
			root = new_node();
			a[root].info = value;
			update(root);
			return;
		}
		if (value == a[root].info) {
			a[root].info += value;
			update(root);
			return;
		}
		cmptype = type;
		if (value < a[root].info) insert(a[root].lc, value, type ^ 1);
		else insert(a[root].rc, value, type ^ 1);
		update(root);
		if (unbalance(root)) {
			reroot = root;
			retype = type;
		}
	}
	void insert(int qx, int qy, int qv) {
		point tmp = (point) {qx, qy, qv};
		reroot = 0;
		insert(root, tmp, 0);
		if (reroot) rebuild();
	}
	void query(int root) {
		if (a[root].Lx >= qlx && a[root].Ly >= qly && a[root].Rx <= qrx && a[root].Ry <= qry) {
			ans += a[root].sum;
			return;
		}
		if (a[root].info.x >= qlx && a[root].info.y >= qly && a[root].info.x <= qrx && a[root].info.y <= qry) ans += a[root].info.v;
		if (a[root].lc) {
			int tmp = a[root].lc;
			if (a[tmp].Lx <= qrx && a[tmp].Ly <= qry && a[tmp].Rx >= qlx && a[tmp].Ry >= qly) query(tmp);
		}
		if (a[root].rc) {
			int tmp = a[root].rc;
			if (a[tmp].Lx <= qrx && a[tmp].Ly <= qry && a[tmp].Rx >= qlx && a[tmp].Ry >= qly) query(tmp);
		}
	}
	int query(int lx, int ly, int rx, int ry) {
		ans = 0;
		qlx = lx; qly = ly;
		qrx = rx; qry = ry;
		query(root);
		return ans;
	}
} KDT;
int main() {
	KDT.init(MAXN - 1);
	int n, opt;
	read(n);
	for (read(opt); opt != 3; read(opt)) {
		if (opt == 1) {
			int x, y, v;
			read(x), read(y), read(v);
			KDT.insert(x, y, v);
		} else {
			int lx, ly, rx, ry;
			read(lx), read(ly), read(rx), read(ry);
			printf("%d\n", KDT.query(lx, ly, rx, ry));
		}
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/80077733