[BZOJ1176][Balkan2007]Mokia

1176: [Balkan2007]Mokia

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 2633  Solved: 1184
[Submit][Status][Discuss]

Description

维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

Input

第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

接下来每行为一下三种输入之一(不包含引号):

"1 x y a"

"2 x1 y1 x2 y2"

"3"

输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出

输入3:表示输入结束

Output

对于每个输入2,输出一行,即输入2的答案

Sample Input

0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3

Sample Output

3
5

HINT

 

保证答案不会超过int范围

 

CDQ分治

还是把每种查询拆成四个

然后时间直接不用排了。。

在分治过程中按照$x$归并,然后一边归并一边把$y$加到权值树状数组里面

树状数组清空可以打时间戳

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char buf[10000000], *ptr = buf - 1;
inline int readint() {
    int f = 1, n = 0;
    char ch = *++ptr;
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = *++ptr;
    }
    while (ch <= '9' && ch >= '0') {
        n = (n << 1) + (n << 3) + ch - '0';
        ch = *++ptr;
    }
    return f * n;
}
int s, w;
int C[2000000 + 10], T[2000000 + 10] = { 0 }, flag = 0;
inline int Query(int pos) {
    int ret = 0;
    for (int i = pos; i; i -= i & -i)
        if (T[i] == flag) ret += C[i];
    return ret;
}
inline void Update(int pos, int val) {
    for(int i = pos; i <= w; i += i & -i)
        if (T[i] != flag) {
            T[i] = flag;
            C[i] = val;
        }
        else C[i] += val;
}
struct Que {
    int type, x, y, val;
    Que() {}
    Que(int _type, int _x, int _y, int _val) : type(_type), x(_x), y(_y), val(_val) {}
}q[200000 + 10], tp[200000 + 10];
int ans[10000 + 10] = {0};
void CDQ(int l, int r) {
    if (l == r) return;
    int mid = l + r >> 1, ll = l, rr = mid + 1, tcnt = 0;
    CDQ(l, mid); CDQ(mid + 1, r);
    flag++;
    while (ll <= mid && rr <= r) {
        if (q[ll].x <= q[rr].x) {
            if (q[ll].type == 1) Update(q[ll].y, q[ll].val);
            tp[++tcnt] = q[ll++];
        }
        else {
            if (q[rr].type == 2) ans[q[rr].val] += Query(q[rr].y);
            else if(q[rr].type == 3) ans[q[rr].val] -= Query(q[rr].y);
            tp[++tcnt] = q[rr++];
        }
    }
    while (ll <= mid) tp[++tcnt] = q[ll++];
    while (rr <= r) {
        if (q[rr].type == 2) ans[q[rr].val] += Query(q[rr].y);
        else if(q[rr].type == 3) ans[q[rr].val] -= Query(q[rr].y);
        tp[++tcnt] = q[rr++];
    }
    for (int i = 1; i <= tcnt; i++) q[l + i - 1] = tp[i];
}
int sz = 0;
int main() {
    fread(buf, sizeof(char), sizeof(buf), stdin);
    s = readint();
    w = readint();
    int opt, x1, y1, x2, y2, a, qtime = 0;
    while ((opt = readint()) != 3) {
        x1 = readint();
        y1 = readint();
        if (opt == 1) {
            a = readint();
            q[++sz] = Que(1, x1, y1, a);
        }
        else {
            qtime++;
            x2 = readint();
            y2 = readint();
            q[++sz] = Que(2, x2, y2, qtime);
            q[++sz] = Que(2, x1 - 1, y1 - 1, qtime);
            q[++sz] = Que(3, x1 - 1, y2, qtime);
            q[++sz] = Que(3, x2, y1 - 1, qtime);
        //    ans[qtime] = (x2 - x1 + 1) * (y2 - y1 + 1) * s;
        }
    }
    CDQ(1, sz);
    for (int i = 1; i <= qtime; i++)
        printf("%d\n", ans[i]);
    return 0;
}

 

posted @ 2017-09-29 21:15  Elder_Giang  阅读(125)  评论(0编辑  收藏  举报