bzoj 1176 CDQ分治
思路:首先我们将问题转换一下,变成问在某个点左下角的权值和,那么每一个询问可以拆成4的这样的询问,然后
进行CDQ 分治,回溯的时候按x轴排序,然后用树状数组维护y的值。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> #define x2 skdjflsdg #define y2 sdkfjsktge using namespace std; const int N = 2e6 + 7; const int M = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int s, w, cnt, tot, op; LL ans[M], a[N]; struct Qus { int x, y, idx, id; } qus[M], tmp[M]; void modify(int x, int v) { for(int i = x; i < N; i += i & -i) { a[i] += v; } } LL sum(int x) { LL ans = 0; for(int i = x; i; i -= i & -i) { ans += a[i]; } return ans; } void cdq(int l, int r) { if(l == r) return; int mid = l + r >> 1; cdq(l, mid); cdq(mid + 1, r); int p = l, q = mid + 1, cnt = l; for(int i = mid + 1; i <= r; i++) { while(p <= mid && qus[p].x <= qus[i].x) { if(qus[p].idx == 0) modify(qus[p].y, qus[p].id); p++; } ans[qus[i].id] += qus[i].idx * sum(qus[i].y); } for(int i = l; i < p; i++) { if(qus[i].idx == 0) { modify(qus[i].y, -qus[i].id); } } p = l, q = mid + 1, cnt = l; while(p <= mid && q <= r) { if(qus[p].x <= qus[q].x) { tmp[cnt++] = qus[p++]; } else { tmp[cnt++] = qus[q++]; } } while(p <= mid) tmp[cnt++] = qus[p++]; while(q <= r) tmp[cnt++] = qus[q++]; for(int i = l; i <= r; i++) qus[i] = tmp[i]; } int main() { scanf("%d%d", &s, &w); while(scanf("%d", &op) && op < 3) { if(op == 1) { int x, y, a; scanf("%d%d%d", &x, &y, &a); x += 2; y += 2; qus[++tot].x = x; qus[tot].y = y; qus[tot].id = a; qus[tot].idx = 0; } else { int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); x1 += 2, y1 += 2; x2 += 2, y2 += 2; qus[++tot].x = x2; qus[tot].y = y2; qus[tot].id = ++cnt; qus[tot].idx = 1; qus[++tot].x = x2; qus[tot].y = y1 - 1; qus[tot].id = cnt; qus[tot].idx = -1; qus[++tot].x = x1 - 1; qus[tot].y = y2; qus[tot].id = cnt; qus[tot].idx = -1; qus[++tot].x = x1 - 1; qus[tot].y = y1 - 1; qus[tot].id = cnt; qus[tot].idx = 1; ans[cnt] = 1ll * (x2 - x1) * (y2 - y1) * s; } } cdq(1, tot); for(int i = 1; i <= cnt; i++) printf("%lld\n", ans[i]); return 0; } /* */