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;
}