牛客网暑期ACM多校训练营第二场J - 二进制状态压缩

题目链接:点击这里

 

解题思路:只要田上被施上一次不同的肥料那么植物就死了。那么我们知道两个值不同那么他们的二进制位至少有一位是不同的。

根据这一特点,先可以用前缀和求出一块田被施了几次肥。然后枚举每个二进制位,将原来的施肥操作变为施肥值的该二进制位是1才施肥,那么如果一块田两次施肥次数不等,说明该块田至少被一个不等于田地值的肥料施过,那么他肯定就废了。

 

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<set>
#define inf 0x3f3f3f3f
#define gi(i) scanf("%d",&i)
using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
int a[N],s[N],f[N];
#define y1 y_1
int x1[N],y1[N],x2[N],y2[N],tp[N];
int n,m;
bool die[N];
#define id(x,y) (((x)-1)*m+(y))
void add(int k,int *f) {
	++f[id(x1[k],y1[k])];
	if (x2[k]<n) --f[id(x2[k]+1,y1[k])];
	if (y2[k]<m) --f[id(x1[k],y2[k]+1)];
	if (x2[k]<n&&y2[k]<m) ++f[id(x2[k]+1,y2[k]+1)];
}
void work(int *s) {
	int i,j,t;
	for (i=t=1;i<=n;i++)
		for (j=1;j<=m;j++,t++) {
			if (i>1) s[t]+=s[t-m];
			if (j>1) s[t]+=s[t-1];
			if (i>1&&j>1) s[t]-=s[t-m-1];
		}
}
int main()
{
	int i,v,T;
	gi(n),gi(m),gi(T);
	for (i=1;i<=n*m;i++)
		gi(a[i]);
	for (i=1;i<=T;i++) {
		gi(x1[i]),gi(y1[i]),gi(x2[i]),gi(y2[i]),gi(tp[i]);
		add(i,s);
	}
	work(s);
	for (v=0;v<20;v++) {
		for (i=1;i<=n*m;i++) f[i]=0;
		for (i=1;i<=T;i++)
			if (tp[i]>>v&1) {
				add(i,f);
			}
		work(f);
		for (i=1;i<=n*m;i++)
			if (a[i]>>v&1) {
				if (f[i]!=s[i]) {
					die[i]=true;
				}
			} else {
				if (f[i]) {
					die[i]=true;
				}
			}
	}
	v=0;
	for (i=1;i<=n*m;i++) {
		v+=die[i];
	}
	printf("%d\n",v);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值