棋盘(二维差分)

发布于:2025-02-10 ⋅ 阅读:(39) ⋅ 点赞:(0)

题目:

5396. 棋盘

小蓝拥有 n×nn×n 大小的棋盘,一开始棋盘上全都是白子。

小蓝进行了 mm 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色,黑色棋子变为白色)。

请输出所有操作做完后棋盘上每个棋子的颜色。

输入格式

输入的第一行包含两个整数 n,mn,m,用一个空格分隔,表示棋盘大小与操作数。

接下来 mm 行每行包含四个整数 x1,y1,x2,y2x1,y1,x2,y2,相邻整数之间使用一个空格分隔,表示将在 x1x1 至 x2x2 行和 y1y1 至 y2y2 列中的棋子颜色取反。

输出格式

输出 nn 行,每行 nn 个 00 或 11 表示该位置棋子的颜色。

如果是白色则输出 00,否则输出 11。

数据范围

对于 30%30% 的评测用例,1≤n,m≤5001≤n,m≤500;
对于所有评测用例,1≤n,m≤20001≤n,m≤2000,1≤x1≤x2≤n1≤x1≤x2≤n,1≤y1≤y2≤n1≤y1≤y2≤n。

输入样例:
3 3
1 1 2 2
2 2 3 3
1 1 3 3
输出样例:
001
010
100

代码:

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

const int N=2010;
int diff[N][N],a[N][N];
//a代表棋盘上的数组,即黑白0,1。开始时都为0(白)
//最终求得的差分数组是棋盘上该位置操作的数量。偶数为0,奇数为1
void insert(int x1,int y1,int x2,int y2,int c){
    diff[x1][y1]+=c;
    diff[x2+1][y1]-=c;
    diff[x1][y2+1]-=c;
    diff[x2+1][y2+1]+=c;
}

int main(){
    
    int n,m;
    cin>>n>>m;
    
    //求差分数组,因为a[i][j]都为0,所以直接插0就行
    //其实这部可以不用写
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            insert(i,j,i,j,0);
        }
    }
    
    
    while(m--){
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        //每一次对一个矩阵区间进行反转操作,理解为对该区间进行加1
        insert(x1,y1,x2,y2,1);
    }
    
    //求原数组,前缀和
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            diff[i][j]+=diff[i-1][j]+diff[i][j-1]-diff[i-1][j-1];
        }
    }
    //输出
     for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(diff[i][j]%2==0){//是偶数
               cout<<0;
            }else{
               cout<<1;
            }
        }
        cout<<"\n";
    }
    return 0;
}

判断奇偶可用&1,时间更快点 

 //输出
     for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cout<<(diff[i][j]&1);
        }
        cout<<"\n";
    }

思路:

操作次数为奇数时最终该位置为黑色1,偶数次时,最终为白色0.根据此规律我们可以记录每次该位置的操作数,让此区域的数量都加1。

对某一矩阵区间进行操作,+1操作-->在此区间所有的数都加上一个1。可以考虑用二维差分来操作。insert(x1,y1,x2,y2,1)

最后让差分数组求和来求得操作后(相应区间的数+1)的数组。判断此数组中奇数和偶数的个数,来输出1/0。


网站公告

今日签到

点亮在社区的每一天
去签到