BZOJ 1176 Mokia

CDQ分治

求矩形面积可以看成类似二位前缀和的加减

这样就可以把题目看成x,y,t的三维偏序问题,直接上CDQ分治。

这里不用去重,但是我们在排序的时候一定要把三个维度相同的询问放在修改后面,因为CDQ每次分治都是计算左边对右边的贡献。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define __fastIn ios::sync_with_stdio(false), cin.tie(0)
#define pb push_back
using namespace std;
using LL = long long;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int ret = 0, w = 0; char ch = 0;
    while(!isdigit(ch)){
        w |= ch == '-', ch = getchar();
    }
    while(isdigit(ch)){
        ret = (ret << 3) + (ret << 1) + (ch ^ 48);
        ch = getchar();
    }
    return w ? -ret : ret;
}
template <typename A>
inline A __lcm(A a, A b){ return a / __gcd(a, b) * b; }
template <typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}
const int N = 2000005;
int cur, opt, t, n, cnt, c[N], ans[N];
struct Query{
    int op, id, x, y, t, val;
    Query(){}
    Query(int x, int y, int t, int val): x(x), y(y), t(t), val(val){
        op = id = 0;
    }
    Query(int op, int id, int x, int y, int t, int val): op(op), id(id), x(x), y(y), t(t), val(val){}
    bool operator < (const Query &rhs) const {
        if(x != rhs.x) return x < rhs.x;
        if(y != rhs.y) return y < rhs.y;
        if(t != rhs.t) return t < rhs.t;
        return val > rhs.val;
    }
}v[N], aux[N];

inline void add(int k, int val){
    for(; k <= t; k += lowbit(k)) c[k] += val;
}

inline int query(int k){
    int ret = 0;
    for(; k; k -= lowbit(k)) ret += c[k];
    return ret;
}

void CDQ(int l, int r){
    if(l == r) return;
    int mid = (l + r) >> 1;
    CDQ(l, mid), CDQ(mid + 1, r);
    for(int i = l; i <= r; i ++){
        aux[i - l] = v[i];
    }
    int i = 0,  j = mid + 1 - l;
    for(int k = l; k <= r; k ++){
        if(i > mid - l){
            if(aux[j].op != 0) ans[aux[j].id] += aux[j].op * query(aux[j].t);
            v[k] = aux[j ++];
        }
        else if(j > r - l){
            if(aux[i].op == 0) add(aux[i].t, aux[i].val);
            v[k] = aux[i ++];
        }
        else if(aux[i].y <= aux[j].y){
            if(aux[i].op == 0) add(aux[i].t, aux[i].val);
            v[k] = aux[i ++];
        }
        else{
            if(aux[j].op != 0) ans[aux[j].id] += aux[j].op * query(aux[j].t);
            v[k] = aux[j ++];
        }
    }
    for(int k = 0; k < mid - l + 1; k ++){
        if(aux[k].op == 0) add(aux[k].t, -aux[k].val);
    }
}

int main(){

    for(;;){
        opt = read();
        if(opt == 3) break;
        else if(opt == 0) n = read() + 1;
        else if(opt == 1){
            int x = read() + 1, y = read() + 1, w = read();
            v[++cur] = Query(x, y, ++ t, w);
        }
        else{
            int x1 = read() + 1, y1 = read() + 1, x2 = read() + 1, y2 = read() + 1;
            cnt ++, t ++;
            v[++cur] = Query(1, cnt, x2, y2, t, 0);
            v[++cur] = Query(-1, cnt, x2, y1 - 1, t, 0);
            v[++cur] = Query(-1, cnt, x1 - 1, y2, t, 0);
            v[++cur] = Query(1, cnt, x1 - 1, y1 - 1, t, 0);
        }
    }
    sort(v + 1, v + cur + 1);
    CDQ(1, cur);
    for(int i = 1; i <= cnt; i ++){
        printf("%d\n", ans[i]);
    }
    return 0;
}
posted @ 2019-08-22 17:50  清楚少女ひなこ  阅读(180)  评论(0编辑  收藏  举报