【题目链接】
【三倍经验链接】
【思路要点】
- 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, s; int ans, qlx, qly, qrx, qry; void init(int n, int x) { for (int i = 1; i <= n; i++) mem[i] = i; top = 1; s = x; } 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 + (rx - lx + 1) * (ry - ly + 1) * s; } } KDT; int main() { int n, s, opt; read(s), read(n); KDT.init(MAXN - 1, s); 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; }