POJ 2155 Matrix (树状数组 && 区间计数)

题意 : 给出一个N*N的矩阵, 矩阵只有可能包含0或1, 一开始则全部是0。对于矩阵可以进行两种操作, 第一种是输入 C x1 y1 x2 y2 表示, 对以(x1, y1)为左上角, 以(x2, y2)为右下角构成的矩形区域内的数全部进行取反操作, 即0变1、1变0。第二种是Q X Y, 表示查询现在这个矩阵的(X, Y)点到底是0还是1。总共有T次操作, 对于C操作进行相应的修改, 对于Q操作要对应输出!

分析 : 据说是楼教主出的题, 自己确实想不出什么高效的办法, 参考网上的题解, 才得知解题思想源自一篇国家队论文, 说简单一点就是对于题目要求的C操作, 实际上只要更新这个小矩形区域的四个点即可, 也就是不必全部照样更新。在Q操作查询时候也只要进行二维的树状数组进行(1,1)到(X, Y)点的矩形区域求和, 然后将求和结果%2, 如果得1即这个点被进行了奇数次操作, 所以应为1, 得0则反之。至于为什么或者如何做, 论文比讲的很清楚, 请百度: 《浅谈信息学竞赛中的“0”和“1”

瞎想:很值得借鉴的是对于是否是0或1的判断, 被转化成判断了对这个点操作次数的奇偶。还有对于区间的修改, 对于一维只进行两点的起始标记, 二维则进行四个点的起始标记, 这个也是厉害!

#include<stdio.h>
#include<string.h>
#define lowbit(i) (i&(-i))
const int maxn = 1001;
int c[maxn][maxn], n;
inline void add(int row, int col)
{
    for(int i=row; i<=n; i+=lowbit(i)){
        for(int j=col; j<=n; j+=lowbit(j)){
            c[i][j]++;
        }
    }
}
int sum(int row, int col)
{
    int ans = 0;
    for(int i=row; i>0; i-=lowbit(i)){
        for(int j=col; j>0; j-=lowbit(j)){
            ans += c[i][j];
        }
    }
    return ans;
}
inline void initialize(int k)
{
    for(int i=0; i<=k; i++){
        memset(c[i], 0, sizeof(c[i]));
    }
}
int main(void)
{
    int nCase;
    scanf("%d", &nCase);
    while(nCase--){
        scanf("%d", &n);
        initialize(n);
        int num;
        scanf("%d", &num);
        while(num--){
            char command;
            scanf(" %c", &command);
            if(command==‘C‘){
                int x1, y1, x2, y2;
                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                add(x1, y1);
                add(x2+1, y1);
                add(x1, y2+1);
                add(x2+1, y2+1);
            }else{
                int x, y;
                scanf("%d%d", &x, &y);
                int SUM = sum(x, y);
                printf("%d\n", SUM&1);//&1和%2好像效率一样!
            }
        }
        puts("");//注意这里, 用例之间要空个行, 避免PE
    }
    return 0;
}

时间: 2024-10-21 04:24:35

POJ 2155 Matrix (树状数组 && 区间计数)的相关文章

poj 2155 Matrix(树状数组的应用)

http://poj.org/problem?id=2155 对于一个n*n(n <= 1000)的01矩阵,初始全为0,有两种操作. C x1 y1 x2 y2 ,分别代表矩阵的左上角和右下角,将这个矩阵中的01互换,原为0的变为1,原为1的变为0. Q x y询问A[x,y]现在是几. 因为只有01的互换,且原始为0,那么只需计算[x,y]处被换了几次就能确定现在这个格子是几.重点就是怎样快速计算[x,y]格子被换了几次.操作方法是将[x1,y1][x1,y2+1][x2+1,y1][x2+

TOJ 2722 Matrix(树状数组区间取反单点查询)

描述 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 <= i, j <= N). We can change the matrix in the following way. Given a rectangle whose upper-left c

POJ 1195-Mobile phones(二维树状数组-区间更新区间查询)

Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 17661   Accepted: 8173 Description Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The

HRBUST 1161 树状数组区间更新求和

Leyni Time Limit: 3000 MS Memory Limit: 65536 K Total Submit: 267(64 users) Total Accepted: 82(57 users) Rating: Special Judge: No Description Leyni被人掳走,身在水深火热之中... 小奈叶为了拯救Leyni,独自一人前往森林深处从静竹手中夺回昏迷中的Leyni. 历经千辛万苦,小奈叶救出了Leyni,但是静竹为此极为恼怒,决定对他们发起最强烈的进攻.

hdu 1116 敌兵布阵(树状数组区间求最值)

题意: 给出一行数字,然后可以修改其中第i个数字,并且可以询问第i至第j个数字的和(i <= j). 输入: 首行输入一个t,表示共有t组数据. 接下来每行首行输入一个整数n,表示共有n个数字. 接下来每行首先输入一个字符串,如果是”Add”,接下来是两个整数a,b,表示给第i个数增加b.如果是”Query”,接下来是两个整数a,b,表示查询从第i个数到第j个数之间的和.如果是”End”,表示这组数据结束. 输出: 每组数据首先输出”Case X: ”,其中X表示第x组数. 每次查询,输出计算结

POJ 2309 BST 树状数组基本操作

Description Consider an infinite full binary search tree (see the figure below), the numbers in the nodes are 1, 2, 3, .... In a subtree whose root node is X, we can get the minimum number in this subtree by repeating going down the left node until t

hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8984    Accepted Submission(s): 4594 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球

hdu 1754 I Hate It(树状数组区间求最值)2007省赛集训队练习赛(6)_linle专场

题意: 输入一行数字,查询第i个数到第j个数之间的最大值.可以修改其中的某个数的值. 输入: 包含多组输入数据. 每组输入首行两个整数n,m.表示共有n个数,m次操作. 接下来一行包含n个整数. 接下来m行,每行包含一个字母s,两个整数a,b. 当s为’Q’,表示查询第a个数到第b个数之间的最大值. 当s为’U’,表示将第a个数更改为b. 输出: 每次查询输出一个结果,每次输出占一行. 题解: 点修改区间求最值,可以用树状数组模板. 具体见代码—— 1 #include <cstdio> 2

树状数组区间更新

在今天的文章开始之前,给大家提一个建议,由于线段树和树状数组这两个结构的分析有很多联系,因此,建议没有看前几篇文章的朋友一定需要了解一下前面的内容.链接如下: 线段树+RMQ问题第二弹 线段树第二弹(区间更新) 树状数组(Binary Indexed Tree,BIT) 上篇文章我们讨论了树状数组的基本结构以及它最擅长的两个功能:单点更新和区间求和,今天,我们来接着上一篇文章的内容继续深入研究.上篇文章我们是将树状数组和线段树进行对比讲解的,既然线段树的章节我们介绍了区间求和.区间最值.单点更新