关闭

[TYVJ P1716/BZOJ 3132 上帝造题的七分钟] 二维树状数组区间修改、区间查询

标签: bit树状数组数据结构
586人阅读 评论(0) 收藏 举报
分类:

[TYVJ P1716/BZOJ 3132 上帝造题的七分钟] 二维树状数组区间修改、区间查询

知识点:data structure binary index tree

1. 题目链接

[TYVJ P1716 上帝造题的七分钟]
类似题目还有[POJ 2155 Matrix]。只不过这个题目就是一个二维的区间翻转,单点查询。一个树状数组就可以做了,但是可以套上这题的模板做,如果你不闲麻烦的话。。

2. 题意描述

有一个nm的矩阵,有2种操作(操作次数不超过200000次)。
操作一:二维区间修改,选一个子矩阵【以(a,b),(c,d)为顶点】,进行区间加上delta
操作二:二维区间求和,选一个子矩阵【以(a,b),(c,d)为顶点】,求这个子矩阵的所有元素之和。

3. 解题思路

BZOJ 3132这个题目好像找不到了?就在TYVJ上找到这个题目了。
二维树状数组区间修改、区间查询的裸题。但是这个题目有点剧毒,可能是卡常特别严重?TLE了很多次,加上超级输入挂,依旧TLE,非得再加一个输出挂。
二维树状数组区间修改,区间更新原理:
跟一维树状数组区间修改,区间更新的原理类似。也是用差分增量数据来表示一个前缀和。然后用前缀和描述区间。
对于原矩阵A,用矩阵dij表示(1,1)(n,m)的增量,那么子矩阵(1,1)(x,y)的和为:

sum=i=1xj=1y[di,j(xi+1)(yi+1)]=i=1xj=1y{di,j[(x+1)(y+1)(x+1)j(y+1)i+ij]}=i=1xj=1y[(x+1)(y+1)dij(x+1)jdij(y+1)idij+ijdij]

因此,用四个树状数组分别维护:dij,(idij),(jdij),(ijdij)
最后,贴一个二维树状数组的模板。

4. 实现代码

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int MAXN = 2048 + 1;

int n, m;
// 输入挂
namespace IO {
    const int MT = 10 * 1024 * 1024;  /// 10MB 请注意输入数据的大小!!!
    char IO_BUF[MT];
    int IO_PTR, IO_SZ;
    /// 要记得把这一行添加到main函数第一行!!!
    void begin() {
        IO_PTR = 0;
        IO_SZ = fread (IO_BUF, 1, MT, stdin);
    }
    template<typename T>
    inline bool scan_d (T & t) {
        while (IO_PTR < IO_SZ && IO_BUF[IO_PTR] != '-' && (IO_BUF[IO_PTR] < '0' || IO_BUF[IO_PTR] > '9'))
            IO_PTR ++;
        if (IO_PTR >= IO_SZ) return false;
        bool sgn = false;
        if (IO_BUF[IO_PTR] == '-') sgn = true, IO_PTR ++;
        for (t = 0; IO_PTR < IO_SZ && '0' <= IO_BUF[IO_PTR] && IO_BUF[IO_PTR] <= '9'; IO_PTR ++)
            t = t * 10 + IO_BUF[IO_PTR] - '0';
        if (sgn) t = -t;
        return true;
    }
    inline bool scan_s (char s[]) {
        while (IO_PTR < IO_SZ && (IO_BUF[IO_PTR] == ' ' || IO_BUF[IO_PTR] == '\n') ) IO_PTR ++;
        if (IO_PTR >= IO_SZ) return false;
        int len = 0;
        while (IO_PTR < IO_SZ && IO_BUF[IO_PTR] != ' ' && IO_BUF[IO_PTR] != '\n')
            s[len ++] = IO_BUF[IO_PTR], IO_PTR ++;
        s[len] = '\0';
        return true;
    }
    template<typename T>
    void print(T x) {
        static char s[33], *s1; s1 = s;
        if (!x) *s1++ = '0';
        if (x < 0) putchar('-'), x = -x;
        while(x) *s1++ = (x % 10 + '0'), x /= 10;
        while(s1-- != s) putchar(*s1);
    }
    template<typename T>
    void println(T x) {
        print(x); putchar('\n');
    }
};

template<class T>
struct BIT_2D {
    struct Core {
        T C[4][MAXN][MAXN];
        void I() { memset(C, 0, sizeof(C)); }
        inline T lowbit(const T& x) { return x & (-x); }
        void update(const int& x0, const int& y0, const T& val) {
            for(int x = x0; x <= n; x += x & (-x)) {
                for(int y = y0; y <= m; y += y & (-y)) {
                    C[0][x][y] += val;
                    C[1][x][y] += val * x0;
                    C[2][x][y] += val * y0;
                    C[3][x][y] += val * x0 * y0;
                }
            }
        }
        T query(const int& x0, const int& y0) {
            T ret = 0;
            for(int x = x0; x > 0; x -= x & (-x)) {
                for(int y = y0; y > 0; y -= y & (-y)) {
                    ret += C[0][x][y] * (x0 + 1) * (y0 + 1);
                    ret -= C[1][x][y] * (y0 + 1);
                    ret -= C[2][x][y] * (x0 + 1);
                    ret += C[3][x][y];
                }
            }
            return ret;
        }
    };
    Core core;
    void update(const int& x0, const int& y0, const int& x1, const int& y1, const int& val) {
        int dx[4] = {x0, x1 + 1, x0, x1 + 1};
        int dy[4] = {y0, y1 + 1, y1 + 1, y0};
        int v[4] = {val, val, -val, -val};
        for(int i = 0; i < 4; ++i) {
            core.update(dx[i], dy[i], v[i]);
        }
    }
    int query(const int& x0, const int& y0, const int& x1, const int& y1) {
        int ret = 0;
        int dx[4] = {x0 - 1, x1, x0 - 1, x1};
        int dy[4] = {y0 - 1, y1, y1, y0 - 1};
        int v[4] = {1, 1, -1, -1};
        for(int i = 0; i < 4; ++i) {
            ret += v[i] * core.query(dx[i], dy[i]);
        }
        return ret;
    }
};
BIT_2D<int> bit;

char op[5];
int x[2], y[2], delta;

int main() {
#ifdef ___LOCAL_WONZY___
    freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
    IO::begin();
    while(IO::scan_s(op)) {
        if(op[0] == 'X') {
            IO::scan_d(n);
            IO::scan_d(m);
//            a.I(), b.I(), c.I(), d.I();
            continue;
        }
        IO::scan_d(x[0]);
        IO::scan_d(y[0]);
        IO::scan_d(x[1]);
        IO::scan_d(y[1]);
        if(op[0] == 'k') {
            IO::println(bit.query(x[0], y[0], x[1], y[1]));
        } else {
            IO::scan_d(delta);
            bit.update(x[0], y[0], x[1], y[1], delta);
        }
    }
    return 0;
}
1
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

【树状数组】[CQBZOJ2719]上帝造题的七分钟I

二维树状数组区间修改、查询裸题。#include #define MAXN 2048 int n,m,c[MAXN+10][MAXN+10],ci[MAXN+10][MAXN+10],cj[MAXN+...
  • outer_form
  • outer_form
  • 2015-09-24 13:28
  • 1026

BZOJ 3132: 上帝造题的七分钟【树状数组(二维区间加,区间查询

二维的区间加区间查询,稍微推一下式子就好…… 反正就长那样 我当时肯定没睡醒……喵的……推得都是些什么鬼啊QAQ struct似乎是会跑得快一点……?反正我这个写法慢的一比…… #include #d...
  • Flaze_
  • Flaze_
  • 2016-09-21 15:12
  • 355

树状数组 区间修改,单点查询;

https://www.luogu.org/problem/show?pid=3368#sub 线段树水题啊; 但是我们要学习树状数组; 树状数组水题啊; 首先假如我们会模版1; 其实我们发...
  • largecub233
  • largecub233
  • 2017-02-23 10:54
  • 861

树状数组 --区间查询+区间修改

数据结构
  • FSAHFGSADHSAKNDAS
  • FSAHFGSADHSAKNDAS
  • 2016-09-24 13:45
  • 3841

树状数组的区间修改,单点查询

树状数组的区间修改
  • u013514722
  • u013514722
  • 2014-10-17 21:49
  • 2659

树状数组(单点修改区间查询、区间修改单点查询、区间修改区间查询)

Description如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和Input第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 ...
  • zars19
  • zars19
  • 2017-01-19 22:28
  • 841

bzoj3038 上帝造题的七分钟2

并查集+树状数组
  • sdfzyhx
  • sdfzyhx
  • 2016-10-24 20:44
  • 165

【BZOJ3038】【Codevs2492】上帝造题的七分钟2

喜闻乐见双倍经验 2492 上帝造题的七分钟 2时间限制: 1 s 空间限制: 64000 KB 题目等级 : 大师 Master题目描述 Description  XLk觉得《上帝造题的七分...
  • CreationAugust
  • CreationAugust
  • 2015-04-10 07:34
  • 874

BZOJ 3132 上帝造题的七分钟 [tyvj 1716](关于树状数组)

自从看了这一篇文章,我才觉得我之前相当于没有学树状数组啊。Orz文章的链接:树状数组维护区间和的模型及其拓广的简单总结 贴上我的模板吧。 ///////////////////////////////...
  • SAI_D
  • SAI_D
  • 2015-03-05 21:57
  • 341

【BZOJ 3110】 [Zjoi2013]K大数查询 整体二分+树状数组区间修改

额,只能说整体二分是一个很神奇的东西,首先既然是二分虽然加了一个整体听起来变得立马高大上起来,但是还是需要从最基本的二分思路出发才能理解。首先如果对于只有一次地查询操作的话我们很容易就可以想到二分的写...
  • pbihao
  • pbihao
  • 2016-12-07 19:52
  • 464
    个人资料
    • 访问:295152次
    • 积分:5767
    • 等级:
    • 排名:第5238名
    • 原创:273篇
    • 转载:8篇
    • 译文:0篇
    • 评论:44条
    友情链接
    最新评论