牛客oj farm(二维差分 前缀和,位运算)

题目链接
发现自己以前的博客都没有写题意的习惯,从这篇开始写
题意大概是说一开始给了各种植物类型(1-n×m) 然后开始施肥,如果说是不同种类的肥料就会让植物死掉.在进行了t次矩阵赋值之后问一共死了多少朵花.
区间修改,矩阵修改一般和差分有关.一开始没什么头绪.瞄了一眼别人的题解说考虑位运算就有点想法了.不过实现上的细节也有些不太好写.
说一下位运算的思路.
可以先简化一下问题.如果只有0和1两种类型的话.我们只需要维护矩阵上面各个位置0和1的个数就可以了.如果说这个位置是0种类植物,那么当这个位置上1的个数大于等于1个的时候这个植物就会死掉.如果是1的话就反过来,0的个数大于等于1个的时候就死亡.这样就可以用二维的差分和前缀和解决了.
回到问题本身.他不只0 和 1 两种类型,但是思想是差不多的.除了植物本身需要的类型,其他肥料对他来说都会让他死亡.考虑二进制表示它的种类.如果是不同类型的肥料,那么二进制上面至少会有一个位上不相同.题目数据最大也就1e6,最多就2的20次方那么大的数字.是可以接受的.就只需要把它一位一位拆开来,就可以套到 0 1 类型里面了.
再考虑一个问题,怎么存数据,其实这个是比较麻烦的地方.大体来说有两种方法,第一种就是用vector存,本人c++学的不是很好,用不好.第二种方法是用1维来存二维的数组,这个就好用很多,不过也要注意一下,我看到的题解和我的想法有点不一样.知道了行®和列©就能映射成唯一一个一位数组的下标,也就是i = r*m+c. 具体实现看代码吧.

#include <iostream>
#include <string.h>
using namespace std;
const int N = 5e6+10;
int a[N],cnt[N][2],vis[N]; 
struct Node{
	int x1,x2,y1,y2,x;
};
Node node[N];
int n,m,t,ans=0;
int f(int r,int c){
	return r*m+c;
}
int main(){
    ios::sync_with_stdio(false);
	cin >> n >> m >> t;
	n+=2;m+=2;
	for(int i=1;i<=n-2;++i){
		for(int j=1;j<=m-2;++j){
			cin >> a[f(i,j)];
		}
	}
	for(int i=1;i<=t;++i) cin >> node[i].x1 >> node[i].y1 >> node[i].x2 >> node[i].y2 >> node[i].x;
	for(int k=0;k<=20;++k){
		memset(cnt,0,sizeof(cnt));
		for(int j=1;j<=t;++j){
			cnt[f(node[j].x1,node[j].y1)][node[j].x % 2] ++;
			cnt[f(node[j].x2+1,node[j].y2+1)][node[j].x % 2] ++;
			cnt[f(node[j].x2+1,node[j].y1)][node[j].x % 2] --;
			cnt[f(node[j].x1,node[j].y2+1)][node[j].x % 2] --;
			node[j].x /= 2;
		}
		for(int i=1;i<=n-2;++i){
			for(int j=1;j<=m-2;++j){
				cnt[f(i,j)][1] += cnt[f(i-1,j)][1];
				cnt[f(i,j)][0] += cnt[f(i-1,j)][0];
			}
		}
		for(int i=1;i<=n-2;++i){
			for(int j=1;j<=m-2;++j){
				cnt[f(i,j)][1] += cnt[f(i,j-1)][1];
				cnt[f(i,j)][0] += cnt[f(i,j-1)][0];
			}
		}
		for(int i=1;i<=n-2;++i){
			for(int j=1;j<=m-2;++j){
				if(vis[f(i,j)]) continue;
				if(cnt[f(i,j)][!(a[f(i,j)] % 2)] > 0){
					ans ++ ;
					vis[f(i,j)] = 1;
				}
				a[f(i,j)] /= 2;
			}
		}
	}
	cout << ans;
	
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/104783039