BZOJ 1452 JSOI 2009 Count 二维树状数组

题目大意:有一个m*n的方格,每一个格子有他自己的权值。2种操作:

1.改变一个格子的权值。

2.查询所有的x1 <= x <= x2 && y1 <= y <= y2的中,有多少个格子颜色是c。

思路:好像是二维树状数组的样子,但是不知道怎么搞。后来研究了数据范围,发现格子最大300*300,颜色最多才100种,于是算一下300*300*100*4/1024/1024大概是35M,题目要求64M,可以搞了。(这里算的精确一点,我当时没怎么算,吧颜色开成300的了,结果100+M就MLE了。。)

维护100个二维树状数组,每一个代表一种颜色,然后根据容斥原理计算一个方块区间内的数量。更改的时候要改两次,第一次把之前的减去,然后加上改变之后的。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 310
using namespace std;

int m,n;

struct Complex{
    int tree[MAX][MAX];

    void Fix(int x,int y,int c) {
        for(int i = x;i <= m;i += i&-i)
            for(int j = y;j <= n;j += j&-j)
                tree[i][j] += c;
    }
    int GetSum(int x,int y) {
        int re = 0;
        for(int i = x;i;i -= i&-i)
            for(int j = y;j;j -= j&-j)
                re += tree[i][j];
        return re;
    }
}tree_arr[110];

int src[MAX][MAX];
int asks;

int main()
{
    cin >> m >> n;
    for(int i = 1;i <= m; ++i)
        for(int j = 1;j <= n; ++j) {
            scanf("%d",&src[i][j]);
            tree_arr[src[i][j]].Fix(i,j,1);
        }
    cin >> asks;
    for(int flag,i = 1;i <= asks; ++i) {
        scanf("%d",&flag);
        if(flag == 1) {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            tree_arr[src[x][y]].Fix(x,y,-1);
            src[x][y] = z;
            tree_arr[src[x][y]].Fix(x,y,1);
        }
        else {
            int x1,y1,x2,y2,c;
            scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c);
            int ans = tree_arr[c].GetSum(x2,y2);
            ans -= tree_arr[c].GetSum(x1 - 1,y2);
            ans -= tree_arr[c].GetSum(x2,y1 - 1);
            ans += tree_arr[c].GetSum(x1 - 1,y1 - 1);
            printf("%d\n",ans);
        }
    }
    return 0;
}
时间: 2024-10-24 12:21:11

BZOJ 1452 JSOI 2009 Count 二维树状数组的相关文章

BZOJ 1452: [JSOI2009]Count 二维树状数组

1452: [JSOI2009]Count Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1452 Description Input Output Sample Input Sample Output 1 2 HINT 题意 题解: 裸的二维树状数组 代码: //qscqesze #include <cstdio> #include <cmath&g

BZOJ 1452: [JSOI2009]Count (二维树状数组)

Description Input Output Sample Input Sample Output 1 2 HINT 二维树状数组的简单应用,c数组的第一维坐标相当于哈希.如果是修改操作,修改前 将当前的值的个数以及祖先都减1, 修改后将个数加1. #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include

BZOJ 2738 矩阵乘法(整体二分+二维树状数组)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2738 [题目大意] 给出一个方格图,询问要求求出矩阵内第k小的元素 [题解] 我们对答案的大小进行整体二分,用二维树状数组维护二维区间和, 将超过数量的分治到左区间,不满足的分治到右区间即可. [代码] #include <cstdio> #include <algorithm> #include <cstring> using namespace std;

BZOJ 2244 SDOI2011 拦截导弹 CDQ分治/二维树状数组

题目大意:给定一个序列,每个元素是一个二元组,等概率选择一LIS,求LIS长度以及每个元素被选中的概率 第一问CDQ分治裸上 第二问用每个元素所在的LIS个数/总LIS个数就是答案 每个元素所在的LIS自己必选,然后统计前面的方案数和后面的方案数 以前面的方案数为例,令f[x]为以x结尾的LIS长度,那么有DP方程: g[i]=Σg[j] (f[j]+1=f[i],j<i,a[j].x<a[i].x,a[j].y<a[i].y) 将所有元素按f值排序,分层DP,每层DP是一个三维偏序,上

BZOJ 3594 [Scoi2014]方伯伯的玉米田(二维树状数组)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3594 [题目大意] 给出一个数列,选出k个区间使得区间内数全部加1, 求k次操作之后最长的不下降子序列 [题解] 我们发现,每次的区间右端点一定贪心选到最右端才是最优的, 那么在用树状数组统计的时候,只要一个点被+1了,那么后面的点起码+1, 我们在树状数组后面加一维统计被区间包含的次数,发现也是前缀和关系, 所以用二维树状数组统计答案即可. 为避免自身被重复统计,第二维循环降序.

HDU_2642_二维树状数组

Stars Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others)Total Submission(s): 1628    Accepted Submission(s): 683 Problem Description Yifenfei is a romantic guy and he likes to count the stars in the sky.To make the pr

【二维树状数组】See you~

https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F [题意] 给定一个矩阵,每个格子的初始值为1.现在可以对矩阵有四种操作: A x y n1 :给格点(x,y)的值加n1 D x y n1: 给格点(x,y)的值减n1,如果现在格点的值不够n1,把格点置0 M x1 y1 x2 y2:(x1,y1)移动给(x2,y2)n1个 S x1 y1 x2 y2 查询子矩阵的和 [思路] 当然是二维树状数组 但是一定要注意:lowbi

POJ 1195 Mobile phones(二维树状数组)

题目链接:POJ 1195 题意: 给出一个S*S的矩阵(行.列号从1开始),每个元素初始值为0,有两种操作:一种是第X行第Y列元素值加A:另一种是查询给定范围矩阵的所有元素之和(L<=X<=R,B<=Y<=T). 分析: 查询给定范围矩阵的所有元素之和是二维区间和,可以转换为二维前缀和求值.类比一维前缀和求法,二维区间和S(L, B, R, T) = S(1, 1, R, T) - S(1 ,1, L-1, T) - S(1, 1, R, B-1) + S(1, 1, L-1,

POJ 2155 Matrix(二维树状数组,绝对具体)

Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20599   Accepted: 7673 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1