bzoj2683/4066 简单题
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2683
http://www.lydsy.com/JudgeOnline/problem.php?id=4066
【题解】
学习了一发kdtree
感觉十分神奇
用一个类似于平衡树的来维护平面。
然后由于可能出现复杂度退化,大约10000个点就重构一次。
我这么傻逼把nth_element(...)的t+l打成t+1也是没谁了。。。
upd: 5/5又写了一遍怎么又达成+1了啊。。。。。。。
nth_element(t+l, t+mid, t+r+1);
2683:
# include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e5 + 10; const int mod = 1e9+7; # define FO_OPEN 0 # define RG register # define ST static inline void gmin(int &x, int y) {if(x > y) x = y;} inline void gmax(int &x, int y) {if(x < y) x = y;} inline bool in(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2) { return x1 <= xx1 && xx2 <= x2 && y1 <= yy1 && yy2 <= y2; } inline bool out(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2) { return x1 > xx2 || x2 < xx1 || y1 > yy2 || y2 < yy1; } int D; struct node { int d[2], mi[2], mx[2], l, r; ll v, s; friend bool operator == (node a, node b) { return a.d[0] == b.d[0] && a.d[1] == b.d[1]; } friend bool operator < (node a, node b) { return a.d[D] < b.d[D]; } }t[M]; # define ls T[x].l # define rs T[x].r struct KDT { node T[M], tmp; int siz, rt; inline void set() { siz = rt = 0; } inline void up(int x) { for (int i=0; i<2; ++i) { T[x].mx[i] = T[x].mi[i] = T[x].d[i]; if(ls) gmin(T[x].mi[i], T[ls].mi[i]); if(rs) gmin(T[x].mi[i], T[rs].mi[i]); if(ls) gmax(T[x].mx[i], T[ls].mx[i]); if(rs) gmax(T[x].mx[i], T[rs].mx[i]); } T[x].s = T[x].v + T[ls].s + T[rs].s; } inline void insert(int &x, int d) { if(!x) { x = ++siz; T[x].d[0] = T[x].mi[0] = T[x].mx[0] = tmp.d[0]; T[x].d[1] = T[x].mi[1] = T[x].mx[1] = tmp.d[1]; } if(T[x] == tmp) { T[x].v += tmp.v; T[x].s += tmp.v; return ; } if(tmp.d[d] < T[x].d[d]) insert(ls, d^1); else insert(rs, d^1); up(x); } inline ll query(int x, int x1, int y1, int x2, int y2) { if(!x) return 0; ll ret = 0; if(in(x1, y1, x2, y2, T[x].mi[0], T[x].mi[1], T[x].mx[0], T[x].mx[1])) return T[x].s; if(out(x1, y1, x2, y2, T[x].mi[0], T[x].mi[1], T[x].mx[0], T[x].mx[1])) return 0; if(in(x1, y1, x2, y2, T[x].d[0], T[x].d[1], T[x].d[0], T[x].d[1])) ret += T[x].v; return query(ls, x1, y1, x2, y2) + query(rs, x1, y1, x2, y2) + ret; } inline int rebuild(int l, int r, int d) { if(l>r) return 0; int mid = l+r>>1; D = d; nth_element(t+l, t+mid, t+r+1); T[mid] = t[mid]; T[mid].l = rebuild(l, mid-1, d^1); T[mid].r = rebuild(mid+1, r, d^1); up(mid); return mid; } }T; # undef ls # undef rs int REBUILD_SIZE = 5000; int main() { scanf("%*d"); T.set(); int opt, x1, y1, x2, y2; while(1) { scanf("%d", &opt); if(opt == 3) break; if(opt == 1) { scanf("%d%d%d", &x1, &y1, &x2); T.tmp.d[0] = T.tmp.mx[0] = T.tmp.mi[0] = x1; T.tmp.d[1] = T.tmp.mx[1] = T.tmp.mi[1] = y1; T.tmp.v = x2, T.tmp.s = x2; T.insert(T.rt, 0); if(T.siz == REBUILD_SIZE) { for (int i=1; i<=T.siz; ++i) t[i] = T.T[i]; T.rt = T.rebuild(1, T.siz, 0); REBUILD_SIZE += 5000; } } if(opt == 2) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); printf("%lld\n", T.query(T.rt, x1, y1, x2, y2)); } } return 0; }
4066:
# include <cctype> # include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e5 + 10; const int mod = 1e9+7; # define RG register # define ST static inline ll read() { ll x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); } while(isdigit(ch)) { x = x*10+ch-'0'; ch = getchar(); } return x*f; } inline void gmax(int &x, int y) { if(x < y) x = y; } inline void gmin(int &x, int y) { if(x > y) x = y; } inline bool in(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2) { return x1 <= xx1 && xx2 <= x2 && y1 <= yy1 && yy2 <= y2; } inline bool out(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2) { return x1 > xx2 || x2 < xx1 || y1 > yy2 || y2 < yy1; } int D; struct node { int d[2], mx[2], mi[2], l, r; ll v, s; friend bool operator == (node a, node b) { return a.d[0] == b.d[0] && a.d[1] == b.d[1]; } friend bool operator < (node a, node b) { return a.d[D] < b.d[D]; } }t[M]; # define ls T[x].l # define rs T[x].r node tmp; struct KDTree { node T[M]; int rt, siz; inline void set() { siz = 0; rt = 0; } inline void up(int x) { for (int i=0; i<2; ++i) { T[x].mi[i] = T[x].mx[i] = T[x].d[i]; if(ls) gmin(T[x].mi[i], T[ls].mi[i]); if(rs) gmin(T[x].mi[i], T[rs].mi[i]); if(ls) gmax(T[x].mx[i], T[ls].mx[i]); if(rs) gmax(T[x].mx[i], T[rs].mx[i]); } T[x].s = T[x].v + T[ls].s + T[rs].s; } inline void insert(int &x, int d) { if(!x) { x = ++siz; T[x].d[0] = T[x].mi[0] = T[x].mx[0] = tmp.d[0]; T[x].d[1] = T[x].mi[1] = T[x].mx[1] = tmp.d[1]; } if(tmp == T[x]) { T[x].v += tmp.v; T[x].s += tmp.v; return ; } if(tmp.d[d] < T[x].d[d]) insert(ls, d^1); else insert(rs, d^1); up(x); } inline ll query(int x, int x1, int y1, int x2, int y2) { if(!x) return 0ll; ll ret = 0; if(in(x1, y1, x2, y2, T[x].mi[0], T[x].mi[1], T[x].mx[0], T[x].mx[1])) return T[x].s; if(out(x1, y1, x2, y2, T[x].mi[0], T[x].mi[1], T[x].mx[0], T[x].mx[1])) return 0ll; if(in(x1, y1, x2, y2, T[x].d[0], T[x].d[1], T[x].d[0], T[x].d[1])) ret += T[x].v; ret += query(ls, x1, y1, x2, y2) + query(rs, x1, y1, x2, y2); return ret; } inline int rebuild(int l, int r, int d) { if(l>r) return 0; int mid = l+r>>1; D = d; nth_element(t+l, t+mid, t+r+1); T[mid] = t[mid]; T[mid].l = rebuild(l, mid-1, d^1); T[mid].r = rebuild(mid+1, r, d^1); up(mid); return mid; } }T; # undef ls # undef rs int REBUILD_SIZE = 10000; int main() { int opt, x1, y1, x2, y2; T.set(); ll lst = 0; scanf("%*d"); while(1) { opt = read();if(opt == 3) break; if(opt == 1) { x1 = read() ^ lst, y1 = read() ^ lst, x2 = read() ^ lst; tmp.d[0] = x1, tmp.d[1] = y1, tmp.v = tmp.s = x2; T.insert(T.rt, 0); if(T.siz == REBUILD_SIZE) { for (int i=1; i<=T.siz; ++i) t[i] = T.T[i]; T.rt = T.rebuild(1, T.siz, 0); REBUILD_SIZE += 10000; } } if(opt == 2) { x1 = read() ^ lst, y1 = read() ^ lst, x2 = read() ^ lst, y2 = read() ^ lst; lst = T.query(T.rt, x1, y1, x2, y2); printf("%lld\n", lst); } } return 0; }