Matrix Subtraction

题意:

一个给定的矩阵,然后给定一个子矩阵的大小,子矩阵可以 将覆盖矩阵的区域的值减1,问能否将矩阵全部减为0

题解:

思路和下面这个链接讲的题十分相似
传送
本质就是二维树状数组差分求解
用mp数组来存矩阵,然后对空白的data数组进行构造,构造完对mp进行清理,最后要看data能否构造出mp的样子,也就是看mp是否全为0
从左上角到右下角的顺序开始处理

代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
ll mp[1005][1005];
int m,n,a,b;
int t;



const int MAX = 1123;
ll data[MAX][MAX];

int lowbit(int x) {
   
    return x&-x;
}

void Add(int x, int y, ll w) {
   
    for (int i = x; i <= n; i += lowbit(i)) {
   
        for (int j = y; j <= m; j += lowbit(j)) {
   
            data[i][j] -= w;
        }
    }
}

void Add2(int x, int y, ll w) {
   
    for (int i = x; i <= n; i += lowbit(i)) {
   
        for (int j = y; j <= m; j += lowbit(j)) {
   
            data[i][j] += w;
        }
    }
}


ll Sum(int x, int y) {
   
    ll ans = 0;
    for (int i = x; i > 0; i -= lowbit(i)) {
   
        for (int j = y; j > 0; j -= lowbit(j)) {
   
            ans += data[i][j];
        }
    }
    return ans;
}

int g(){
   
       for(int i=1;i+a-1<=n;i++){
   
            for(int j=1;j+b-1<=m;j++){
   
                ll num=Sum(i,j);
                num=mp[i][j]-num;
                mp[i][j]=num;
                if(mp[i][j]>0){
   
                int x1, x2, y1, y2;
                x1=i;x2=i+a-1;y1=j;y2=j+b-1;
                Add2(x1, y1, mp[i][j]);
                Add(x2+1, y1, mp[i][j]);
                Add(x1, y2+1, mp[i][j]);
                Add2(x2+1, y2+1, mp[i][j]);
                mp[i][j]=0;
                }
				else if(mp[i][j]<0){
   
                     return 1;
                }
            }

        }


        for(int i=1;i<=n;i++){
   
            for(int j=1;j<=m;j++){
   
                if(i>n-a+1||j>m-b+1)mp[i][j]-=Sum(i,j);

                if(mp[i][j]!=0){
   
                    return 1;
                }
            }

        }



        return 0;
}


int main(){
   
    scanf("%d",&t);
    while(t--)
	{
   
        scanf("%d%d%d%d",&n,&m,&a,&b);
        for(int i=1;i<=n;i++)
		{
   
            for(int j=1;j<=m;j++)
			{
   
                scanf("%lld",&mp[i][j]);

            }
        }
        for(int i=1;i<=n;i++)
		{
   
            for(int j=1;j<=m;j++)
			{
   
                data[i][j]=0;

            }
        }
        int sign=g();



        if(sign==0){
   
            printf("^_^\n");
        }else{
   
            printf("QAQ\n");
        }



    }


    return 0;
}