[BZOJ1176][Balkan2007]Mokia && CDQ分治+树状数组

来源:互联网 发布:微信机器人 java 编辑:程序博客网 时间:2024/04/30 12:10

这样的二维矩形和本身可以用树状数组在给定时间内完成 然而这时空间显然开不下了 

那么我们可以用CDQ分治将操作离散化 再将所有操作按坐标排序 这样保证了在解决较大矩阵问题的时候较小矩阵内的操作已经进行了

然后 就没有人然后了 总的来说CDQ分治是对多数次操作离线后再二分处理的一种方法? 然而我还是并不怎么会QAQ

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<queue>#include<map>#define lowbit(x) ((x) & (-(x)))#define SF scanf#define PF printfusing namespace std;typedef long long LL;const int MAXN = 2000000;const int MAXQ = 10000;const int MAXC = 200000;int S, n, m, Q;int ans[MAXQ+10];int c[MAXN+10];struct Node {int x, y, op, val, pos, id;bool operator < (const Node &t) const {if(x != t.x) return x < t.x;else if(y != t.y) return y < t.y;else return op < t.op;}} A[MAXC+10], tmp[MAXC+10];int query(int x) {int ret = 0;for(ret = 0; x; x -= lowbit(x)) ret += c[x];return ret;}void add(int x, int val) {for( ; x <= n; x += lowbit(x)) c[x] += val;}void CDQ(int L, int R) {if(L == R) return ;int mid = (L + R) >> 1, l1, l2;l1 = L; l2 = mid+1;for(int i = L; i <= R; i++) {if(A[i].id <= mid && !A[i].op) add(A[i].y, A[i].val);if(A[i].id > mid && A[i].op) ans[A[i].pos] += A[i].val * query(A[i].y);}for(int i = L; i <= R; i++) if(A[i].id <= mid && !A[i].op) add(A[i].y, -A[i].val);for(int i = L; i <= R; i++) if(A[i].id <= mid) tmp[l1++] = A[i];else tmp[l2++] = A[i];for(int i = L; i <= R; i++) A[i] = tmp[i];CDQ(L, mid); CDQ(mid+1, R);}int main() {int op;SF("%d%d", &S, &n);while(true) {SF("%d", &op);if(op == 1) {m++;SF("%d%d%d", &A[m].x, &A[m].y, &A[m].val);A[m].id = m;}else if(op == 2) {int x1, x2, y1, y2, pos = ++Q;SF("%d%d%d%d", &x1, &y1, &x2, &y2);m++; A[m] = (Node) { x1-1, y1-1, 1, 1, pos, m };m++; A[m] = (Node) { x2, y2, 1, 1, pos, m };m++; A[m] = (Node) { x1-1, y2, 1, -1, pos, m };m++; A[m] = (Node) { x2, y1-1, 1, -1, pos, m };}else break;}sort(A+1, A+1+m);CDQ(1, m);for(int i = 1; i <= Q; i++) PF("%d\n", ans[i]);}


0 0
原创粉丝点击