bzoj 1176 CDQ分治

思路:首先我们将问题转换一下,变成问在某个点左下角的权值和,那么每一个询问可以拆成4的这样的询问,然后

进行CDQ 分治,回溯的时候按x轴排序,然后用树状数组维护y的值。

#include
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair
#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;
}
/*
*/

 

转载于:https://www.cnblogs.com/CJLHY/p/9199277.html

你可能感兴趣的:(bzoj 1176 CDQ分治)