BZOJ 1176 Mokia CDQ分治+树状数组

1176: [Balkan2007]Mokia

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 1854  Solved: 821
[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范围

Solution  

CDQ分治+树状数组裸题,矩阵分成四个点统计,单点更新。

Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;

const int maxn = 2000005;
const int maxm = 160000+10005;
int s, w, ans[maxm];
struct Node
{
    int op, id, x, y, k, to;
    Node (int op = 0, int id = 0, int x = 0, int y = 0, int k = 0, int to = 0):
        op(op), id(id), x(x), y(y), k(k), to(to) {}
    bool operator < (const Node &AI) const
    {
        if (x == AI.x && y == AI.y)
            return op < AI.op;
        if (x == AI.x)
            return y < AI.y;
        return x < AI.x;
    }
}q[maxm], temp[maxm];
struct BIT
{
    int c[maxn+10];
    int lowbit(int x)
    {
        return x & -x;
    }
    void update(int x, int d)
    {
        while (x <= w)
        {
            c[x] += d;
            x += lowbit(x);
        }
    }
    int query(int x)
    {
        int ret = 0;
        while (x > 0)
        {
            ret += c[x];
            x -= lowbit(x);
        }
        return ret;
    }
}T;

void cdq(int l, int r)
{
    if (l == r)
        return ;
    int mid = (l+r)>>1;
    for (int i = l; i <= r; ++i)
    {
        if (q[i].id <= mid && q[i].op == 1)
            T.update(q[i].y, q[i].k);
        if (q[i].id > mid && q[i].op == 2)
            ans[q[i].to] += q[i].k*T.query(q[i].y);
    }
    for (int i = l; i <= r; ++i)
        if (q[i].id <= mid && q[i].op == 1)
            T.update(q[i].y, -q[i].k);
    int t1 = l-1, t2 = mid;
    for (int i = l; i <= r; ++i)
        if (q[i].id <= mid)
            temp[++t1] = q[i];
        else
            temp[++t2] = q[i];
    for (int i = l; i <= r; ++i)
        q[i] = temp[i];
    cdq(l, mid), cdq(mid+1, r);
}

int main()
{
    scanf("%d %d", &s, &w);
    w += 2;
    int oper, cnt = 0, cnt_2 = 0;
    while (~scanf("%d", &oper) && oper != 3)
    {
        if (oper == 1)
        {
            int x, y, d;
            scanf("%d %d %d", &x, &y, &d);
            x += 2, y += 2;
            q[++cnt] = Node(1, cnt, x, y, d, 0);
        }
        else
        {
            int x1, y1, x2, y2;
            scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
            x1 += 2, y1 += 2, x2 += 2, y2 += 2;
            cnt_2 ++;
            ans[cnt_2] = s*(x2-x1+1)*(y2-y1+1);
            q[++cnt] = Node(2, cnt, x2, y2, 1, cnt_2);
            q[++cnt] = Node(2, cnt, x1-1, y2, -1, cnt_2);
            q[++cnt] = Node(2, cnt, x2, y1-1, -1, cnt_2);
            q[++cnt] = Node(2, cnt, x1-1, y1-1, 1, cnt_2);
        }
    }
    sort(q+1, q+cnt+1);
    cdq(1, cnt);
    for (int i = 1; i <= cnt_2; ++i)
        printf("%d\n", ans[i]);
    return 0;
}

 

  

posted @ 2017-02-15 20:30  Splay  阅读(237)  评论(0编辑  收藏  举报