Matrix POJ

题意:
给定 n* n 矩阵A,其元素为0或1. A [ i ] [ j ] 表示第i行和第j列中的数字。最初全为0.
我们有两个操作:

  1. C x1 y1 x2 y2(1 <= x1 <= x2 <= n,1 <= y1 <= y2 <= n)将左上角为(x1,y1),右下角为(x2,y2)的矩阵翻转(0变成1,1变成0)。
  2. Q x y(1 <= x,y <= n)查询A [ x ] [ y ],输出答案。

分析:
0 1 之间的反转可以考虑 “ ^ ” (异或),但这就需要二维线段树的延时标记了,那么有更好的方法吗?
任意数字都可以通过 %2 得到 0 和 1 两个值;
那么我们把矩阵反转改为矩阵所有元素 +1 ,(0+1)%2=1,(1+1)%2=0,0相当于偶数,1相当于奇数,最后询问的时候对答案%2,不就能把 0 1 相互转换改为了矩阵加法修改吗?(还需要用到差分思想,与前缀和思想类似)

AC代码

#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
typedef long long LL;
const int N=1e3+5;
int sum[N][N],n,m;
/// d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]; (差分)
/// a[i][j]=sum[i][j]-sum[i-1][j]-sum[i][j-1]+sum[i-1][j-1]; (前缀和)
/// 由于是差分数组,既可以该减数也可以更改被减数来达到加值的目的,但为了保证所有下标大于1(lowbit!=0),则选择更改减数
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int y,int v)
{
    for(int i=x;i<=n;i+=lowbit(i) )
        for(int j=y;j<=n;j+=lowbit(j) )
            sum[i][j]+=v;

}
void ran_up(int x1,int y1,int x2,int y2)
{
    update(x1,y1,1);
    update(x2+1,y2+1,1);
    update(x1,y2+1,-1);
    update(x2+1,y1,-1);
}
int query(int x,int y)
{
    int ret=0;
    for(int i=x;i>0;i-=lowbit(i) )
        for(int j=y;j>0;j-=lowbit(j) )
            ret+=sum[i][j];
    return ret&1;
}
inline void init()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            sum[i][j]=0;
}
int main()
{
    int T,test=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        if(test++) printf("
");
        while(m--)
        {
            char cmd[5];
            scanf("%s",cmd);
            if(cmd[0]=='C')
            {
                int x1,x2,y1,y2;
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                ran_up(x1,y1,x2,y2);
            }
            else
            {
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%d
",query(x,y) );
            }
        }
    }
    return 0;
}

总的来说是一道区间修改,单点查询的模板题

原文地址:https://www.cnblogs.com/DeepJay/p/12025215.html