题目链接:https://www.nowcoder.com/acm/contest/140/J
题意:
给你N*M个矩阵,每个格子里有种类为k的花。给你t次操作,每次在一个子矩阵里施肥,如果种类为k的肥料被施到不同种类的花上,花就死掉。最后问你死了多少花。
思路:
我们把施肥在同一个矩阵里的种类的肥料加起来,整除以花的种类,如果能整除,说明有可能不会死,但是大多数情况还是错的,如k=5的话,施一次3号肥和一次2号肥也是死的,所以我们可以给花随机一个很大的权值,这个情况就有较大概率避免了。在用二维前缀和处理一波即可。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
#define ll long long
ll hh[N];
ll k;
int main()
{
int n,m,t;
int x1,x2,y1,y2;
srand(time(0));
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=n*m;i++)
{
hh[i]=1e6+i*rand()+1001;;
}
ll **a=new ll *[n+5];
ll **b=new ll *[n+5];
for(int i=0;i<n+5;i++)
{
a[i]=new ll[m+5];
b[i]=new ll[m+5];
}
for(int i=0;i<=n+1;i++)
{
for(int j=0;j<=m+1;j++)
{
a[i][j]=b[i][j]=0;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%lld",&b[i][j]);
b[i][j]=hh[b[i][j]];
}
}
while(t--)
{
scanf("%d%d%d%d%lld",&x1,&y1,&x2,&y2,&k);
k=hh[k];
a[x1][y1]+=k;
a[x1][y2+1]-=k;
a[x2+1][y1]-=k;
a[x2+1][y2+1]+=k;
}
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1];
//cout<<a[i][j]<<' '<<' '<<endl;
if(a[i][j]%b[i][j]!=0)ans++;
}
}
printf("%lld\n",ans);
return 0;
}
思路:
将每一个农田上的数字看成2进制,如果多次施肥中同一块农田上施肥的种类不同,那么这些数字必有一位二进制数不同。先统计每一块农田被使了多少次肥。即统计每一块农田,二进制的每一位有多少个0和1。然后按位遍历,若0,1同时出现,则植物死亡。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+10;
int n,m,t;
int x1[N],Y1[N],x2[N],y2[N],num[N],a[N],b[N],ans[N],c[N];
int id(int x,int y)
{
return (x-1)*m+y;
}
void add(int i,int *s)
{
s[id(x1[i],Y1[i])]++;
if(y2[i]+1<=m) s[id(x1[i],y2[i])+1]--;
if(x2[i]+1<=n) s[id(x2[i]+1,Y1[i])]--;
if(x2[i]+1<=n&&y2[i]+1<=m)
s[id(x2[i]+1,y2[i]+1)]++;
}
void work(int *s)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(j>1) s[id(i,j)]+=s[id(i,j-1)];
if(i>1) s[id(i,j)]+=s[id(i-1,j)];
if(i>1&&j>1) s[id(i,j)]-=s[id(i-1,j-1)];
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=n*m;i++)
{
scanf("%lld",&a[i]);
}
for(int i=1;i<=t;i++)
{
scanf("%d%d%d%d%d",&x1[i],&Y1[i],&x2[i],&y2[i],&num[i]);
add(i,b);
}
work(b);
for(int u=0;u<=20;u++)
{
memset(c,0,sizeof(c));
for(int i=1;i<=t;i++)
{
if((num[i]>>u)&1)
{
add(i,c);
}
}
work(c);
for(int i=1;i<=n*m;i++)
{
bool f;
if((a[i]>>u)&1)
f=true;
else f=false;
if(f)
{
if(b[i]>c[i])ans[i]=1;
}
else
{
if(c[i])ans[i]=1;
}
}
}
int sum=0;
for(int i=1;i<=n*m;i++)
{
if(ans[i])sum++;
}
printf("%d\n",sum);
return 0;
}