KD-tree
强制在线就不能愉快的做这道题了。
我们用KD-tree维护平面上的点,这样建出来的树高大概是log,复杂度过得去,但是插入过多会使树深很深,这样就能卡死,那么我们每个10000次插入就重构一次。
#include<bits/stdc++.h> using namespace std; const int N = 2e5 + 5; int n, root, cnt, m = 10000, d, last; struct data { int x, y, mx_x, mn_x, mx_y, mn_y, lc, rc, sum, val; bool friend operator < (const data &a, const data &b) { if(d == 0) return a.x == b.x ? a.y < b.y : a.x < b.x; if(d == 1) return a.y == b.y ? a.x < b.x : a.y < b.y; } bool friend operator == (const data &a, const data &b) { return a.x == b.x && a.y == b.y; } } a[N], b[N]; inline void read(int &x) { x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + c - '0'; c = getchar(); } x *= f; } bool in(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2) { return X1 >= x1 && Y1 >= y1 && x2 >= X2 && y2 >= Y2; } bool out(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2) { return x1 > X2 || x2 < X1 || y1 > Y2 || y2 < Y1; } void update(int x) { a[x].mn_x = min(a[x].x, min(a[a[x].lc].mn_x, a[a[x].rc].mn_x)); a[x].mx_x = max(a[x].x, max(a[a[x].lc].mx_x, a[a[x].rc].mx_x)); a[x].mn_y = min(a[x].y, min(a[a[x].lc].mn_y, a[a[x].rc].mn_y)); a[x].mx_y = max(a[x].y, max(a[a[x].lc].mx_y, a[a[x].rc].mx_y)); a[x].sum = a[x].val + a[a[x].lc].sum + a[a[x].rc].sum; } int build(int l, int r, int D) { if(l > r) return 0; d = D; int mid = (l + r) >> 1; nth_element(b + l, b + mid, b + r + 1); a[mid] = b[mid]; a[mid].lc = build(l, mid - 1, D ^ 1); a[mid].rc = build(mid + 1, r, D ^ 1); update(mid); return mid; } void insert(int &x, const data &tmp, int D) { d = D; if(!x) { x = ++cnt; a[x].x = a[x].mn_x = a[x].mx_x = tmp.x; a[x].y = a[x].mn_y = a[x].mx_y = tmp.y; a[x].sum = a[x].val = tmp.val; return; } if(a[x] == tmp) { a[x].val += tmp.val; a[x].sum += tmp.val; return; } if(tmp < a[x]) insert(a[x].lc, tmp, D ^ 1); else insert(a[x].rc, tmp, D ^ 1); update(x); } int query(int x, int x1, int y1, int x2, int y2) { if(!x) return 0; int ret = 0; if(in(x1, y1, x2, y2, a[x].mn_x, a[x].mn_y, a[x].mx_x, a[x].mx_y)) return a[x].sum; if(out(x1, y1, x2, y2, a[x].mn_x, a[x].mn_y, a[x].mx_x, a[x].mx_y)) return 0; if(in(x1, y1, x2, y2, a[x].x, a[x].y, a[x].x, a[x].y)) ret += a[x].val; ret += query(a[x].lc, x1, y1, x2, y2) + query(a[x].rc, x1, y1, x2, y2); return ret; } int main() { // freopen("bzoj_4066.in", "r", stdin); // freopen("bzoj_4066.out", "w", stdout); a[0].mn_x = 1e9; a[0].mx_x = -1e9; a[0].mn_y = 1e9; a[0].mx_y = -1e9; b[0].mn_x = 1e9; b[0].mx_x = -1e9; b[0].mn_y = 1e9; b[0].mx_y = -1e9; read(n); while(1) { int opt, x1, y1, x2, y2; data tmp; read(opt); if(opt == 1) { read(tmp.x); read(tmp.y); read(tmp.val); tmp.x ^= last; tmp.y ^= last; tmp.val ^= last; insert(root, tmp, 0); if(cnt == m) { for(int i = 1; i <= cnt; ++i) b[i] = a[i]; root = build(1, cnt, 0); m += 10000; } } if(opt == 2) { read(x1); read(y1); read(x2); read(y2); x1 ^= last; x2 ^= last; y1 ^= last; y2 ^= last; printf("%d ", last = query(root, x1, y1, x2, y2)); } if(opt == 3) break; } // fclose(stdin); // fclose(stdout); return 0; }