zoukankan      html  css  js  c++  java
  • 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;
    }

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

  • 相关阅读:
    POJ 3253 Fence Repair
    POJ 2431 Expedition
    NYOJ 269 VF
    NYOJ 456 邮票分你一半
    划分数问题 DP
    HDU 1253 胜利大逃亡
    NYOJ 294 Bot Trust
    NYOJ 36 最长公共子序列
    HDU 1555 How many days?
    01背包 (大数据)
  • 原文地址:https://www.cnblogs.com/DeepJay/p/12025215.html
Copyright © 2011-2022 走看看