【BZOJ1176】[BOI2007]Mokia 摩基亞
阿新 • • 發佈:2018-12-14
【BZOJ1176】[BOI2007]Mokia 摩基亞
題面
題解
顯然的\(CDQ\)\(/\)樹套樹題
然而根本不想寫樹套樹,那就用\(CDQ\)吧。。。
考慮到點\((x1,y1)\)和\((x2,y2)\)區域內既有上限又有下限我們不是很好算
於是將這個區域的貢獻寫成另外一種形式,
記\((x,y)\)與\((0,0)\)之間區域的貢獻為\(S_{(x,y)}\),則上面的貢獻可表示為
\(S_{(x2,y2)}-S_{(x2,y1-1)}-S_{(y2,x1-1)}+S_{(x1-1,y1-1)}\)
分別統計四個貢獻就很容易辣
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; namespace IO { const int BUFSIZE = 1 << 20; char ibuf[BUFSIZE], *is = ibuf, *it = ibuf; inline char gc() { if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); return *is++; } } inline int gi() { register int data = 0, w = 1; register char ch = 0; while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc(); if (ch == '-') w = -1 , ch = IO::gc(); while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc(); return w * data; } #define MAX_N 200005 #define MAX_W 2000005 struct Node { int x, y, id, w; } t[MAX_N << 2]; int ans[MAX_N]; bool cmp_x(Node a, Node b) { return (a.x == b.x) ? (a.y < b.y) : (a.x < b.x); } int N, c[MAX_W]; inline int lb(int x) { return x & -x; } void add(int x, int v) { while (x <= N) c[x] += v, x += lb(x); } int sum(int x) { int res = 0; while (x > 0) res += c[x], x -= lb(x); return res; } void Div(int l, int r) { if (l == r) return ; int mid = (l + r) >> 1; Div(l, mid); Div(mid + 1, r); int j = l; for (int i = mid + 1; i <= r; i++) { if (t[i].id == 0) continue; for (; t[j].x <= t[i].x && j <= mid; ++j) if (t[j].id == 0) add(t[j].y, t[j].w); ans[t[i].id] += sum(t[i].y) * t[i].w; } for (int i = l; i < j; i++) if (t[i].id == 0) add(t[i].y, -t[i].w); inplace_merge(&t[l], &t[mid + 1], &t[r + 1], cmp_x); } int main () { gi(); N = gi(); int tot = 0, cnt = 0; for (;;) { int op = gi(); if (op == 3) break; int x = gi(), y = gi(); if (op == 1) t[++tot] = (Node){x, y, 0, gi()}; else { int _x = gi(), _y = gi(); ++cnt; t[++tot] = (Node){_x, _y, cnt, 1}; t[++tot] = (Node){_x, y - 1, cnt, -1}; t[++tot] = (Node){x - 1, _y, cnt, -1}; t[++tot] = (Node){x - 1, y - 1, cnt, 1}; } } Div(1, tot); for (int i = 1; i <= cnt; i++) printf("%d\n", ans[i]); return 0; }