[BZOJ2683] 简单题 CDQ分治套树状数组 三维偏序问题

这道题第一眼看到想用二维树状数组去做, 发现数据范围太大了根本开不下, 然后考虑用 C D Q 分治去做, 因为之前用 C D Q 分治做过树状数组模板, 所以我对其采取了同样的套路, 对序列修改只需要把一个询问拆成两个前缀和, 在这里我们把一个询问拆成四个前缀和, 时间这一维默认是有序的, 那么我们 C D Q 分治对 x 排序, 树状数组直接维护 y 的值就好了
题目链接

Codes

#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define mid ((l + r) >> 1)

using namespace std;

const int maxn = 5e5 + 10, maxq = 8e5 + 10;
int n, cnt, tot, ans[maxn], vis[maxq];

namespace Fenwick_Tree {

    int s[maxn];

    void update(int x, int y) {
        while(x <= n) {
            s[x] += y;
            x += x & -x;
        }
    }

    int query(int x) {
        int res = 0;
        while(x) {
            res += s[x];
            x -= x & -x;
        }
        return res;
    }
}

struct node {
    int x, y, z, opt, id;
}Q[maxq], tmp[maxq];

void CDQ(int l, int r) {
    if(l == r) return;
    CDQ(l, mid), CDQ(mid + 1, r);
    int t = l, t1 = l, t2 = mid + 1;
    while(t1 <= mid && t2 <= r) 
        if(Q[t1].x <= Q[t2].x) {
            if(!Q[t1].opt) {
                Fenwick_Tree::update(Q[t1].y, Q[t1].z);
                vis[t] = true;
            }
            tmp[t ++] = Q[t1 ++];
        }
        else {
            ans[Q[t2].id] += Q[t2].opt * Fenwick_Tree::query(Q[t2].y);
            tmp[t ++] = Q[t2 ++];
        }
    while(t1 <= mid) tmp[t ++] = Q[t1 ++];
    while(t2 <= r) {
        ans[Q[t2].id] += Q[t2].opt * Fenwick_Tree::query(Q[t2].y);
        tmp[t ++] = Q[t2 ++];
    }
    For(i, l, r) {
        if(vis[i]) Fenwick_Tree::update(tmp[i].y, -tmp[i].z);
        Q[i] = tmp[i], vis[i] = 0;
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("2683.in", "r", stdin);
    freopen("2683.out", "w", stdout);
#endif
    int k, X1, X2, Y1, Y2;
    scanf("%d", &n);
    while(scanf("%d", &k) && k != 3) {
        if(k == 1) 
            ++ cnt, scanf("%d%d%d", &Q[cnt].x, &Q[cnt].y, &Q[cnt].z);
        else {
            scanf("%d%d%d%d", &X1, &Y1, &X2, &Y2), ++ tot;
            Q[++ cnt].opt = 1, Q[cnt].x = X2, Q[cnt].y = Y2, Q[cnt].id = tot;
            Q[++ cnt].opt = 1, Q[cnt].x = X1 - 1, Q[cnt].y = Y1 - 1, Q[cnt].id = tot;
            Q[++ cnt].opt = -1, Q[cnt].x = X1 - 1, Q[cnt].y = Y2, Q[cnt].id = tot;
            Q[++ cnt].opt = -1, Q[cnt].x = X2, Q[cnt].y = Y1 - 1, Q[cnt].id = tot;
        }
    }
    CDQ(1, cnt);
    For(i, 1, tot)
        printf("%d\n", ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/81266466