1. 程式人生 > >bzoj 2683 簡單題 cdq分治

bzoj 2683 簡單題 cdq分治

bzoj math c++ bits git spa long long 簡單 時間復雜度

題面

題目傳送門

解法

可以離線,那麽就是非常簡單的cdq分治了

只要把詢問拆成4個,然後就變成了一個三維偏序問題

時間復雜度:\(O(q\ log^2\ n)\)

代碼

#include <bits/stdc++.h>
#define int long long
#define N 1000010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar(); x *= f;
}
struct Node {
    int op, tim, x, y, v;
    bool operator < (const Node &a) const {
        return x < a.x;
    }
} a[N], t[N];
int n, f[N], ans[N];
int lowbit(int x) {return x & -x;}
void modify(int x, int v) {
    for (int i = x; i <= n; i += lowbit(i))
        f[i] += v; 
}
int query(int x) {
    int ret = 0;
    for (int i = x; i; i -= lowbit(i))
        ret += f[i];
    return ret;
}
void cdq(int l, int r) {
    if (l == r) return;
    int mid = (l + r) >> 1, tx = l, ty = mid + 1;
    for (int i = l; i <= r; i++)
        if (a[i].tim <= mid) t[tx++] = a[i];
            else t[ty++] = a[i];
    for (int i = l; i <= r; i++) a[i] = t[i];
    tx = l, ty = mid + 1;
    while (ty <= r) {
        while (tx <= mid && a[tx].x <= a[ty].x) {
            if (a[tx].op == 1) modify(a[tx].y, a[tx].v);
            tx++;
        }
        if (a[ty].op == 2) ans[a[ty].v] += query(a[ty].y);
        if (a[ty].op == 3) ans[a[ty].v] -= query(a[ty].y);
        ty++;
    }
    for (int i = l; i < tx; i++) if (a[i].op == 1) modify(a[i].y, -a[i].v);
    cdq(l, mid), cdq(mid + 1, r);
}
main() {
    read(n);
    int len = 0, cntq = 0, op; read(op);
    while (op != 3) {
        if (op == 1) {
            int x, y, v;
            read(x), read(y), read(v);
            a[++len] = (Node) {op, len, x, y, v};
        } else {
            int x1, y1, x2, y2;
            read(x1), read(y1), read(x2), read(y2);
            a[++len] = (Node) {2, len, x2, y2, ++cntq};
            a[++len] = (Node) {3, len, x1 - 1, y2, cntq};
            a[++len] = (Node) {3, len, x2, y1 - 1, cntq};
            a[++len] = (Node) {2, len, x1 - 1, y1 - 1, cntq};
        }
        read(op);
    }
    sort(a + 1, a + len + 1);
    cdq(1, len);
    for (int i = 1; i <= cntq; i++) cout << ans[i] << "\n";
    return 0;
}

bzoj 2683 簡單題 cdq分治