链接:https://www.nowcoder.com/acm/contest/140/J
来源:牛客网
White Rabbit has a rectangular farmland of n*m. In each of the grid there is a kind of plant. The plant in the j-th column of the i-th row belongs the a[i][j]-th type.
White Cloud wants to help White Rabbit fertilize plants, but the i-th plant can only adapt to the i-th fertilizer. If the j-th fertilizer is applied to the i-th plant (i!=j), the plant will immediately die.
Now White Cloud plans to apply fertilizers T times. In the i-th plan, White Cloud will use k[i]-th fertilizer to fertilize all the plants in a rectangle [x1[i]...x2[i]][y1[i]...y2[i]].
White rabbits wants to know how many plants would eventually die if they were to be fertilized according to the expected schedule of White Cloud.
The first line of input contains 3 integers n,m,T(n*m<=1000000,T<=1000000) For the next n lines, each line contains m integers in range[1,n*m] denoting the type of plant in each grid. For the next T lines, the i-th line contains 5 integers x1,y1,x2,y2,k(1<=x1<=x2<=n,1<=y1<=y2<=m,1<=k<=n*m)
Print an integer, denoting the number of plants which would die.
示例1
复制
2 2 2 1 2 2 3 1 1 2 2 2 2 1 2 1 1
复制
3
题意:
在n*m的矩形里,给植物施肥,如果不匹配植物就会死去,问植物死了多少
分析:
如果用树状数组更新区间,再还原过85%,就会TLE,所以用判断该点改变的总和跟(改变的次数与该点的数的乘积)是否相等,这样做会wrong,不会TLE,wrong是因为存在当原数为3,更新4次,分别为1、5、2、4这种情况下,和恰好为改变的次数与该点的数的乘积,这个时候可以做一个映射,消除数与数之间的联系(可以用随机数实现)
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdlib.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
int a[maxn],cnt[maxn],ran[maxn];
ll sum[maxn];
int n,m,t,x,y,z,w,k;
int lowbit(int x){
return x&-x;
}
void update(int x,int y,int add,int d)
{
int tempy=y;
while(x<=n)
{
y=tempy;
while(y<=m)
{
sum[(x-1)*m+y-1]+=add;
cnt[(x-1)*m+y-1]+=d;
y+=lowbit(y);
}
x+=lowbit(x);
}
}
bool query(int x,int y)
{
ll rets=0,retc=0;
int tmp=ran[a[(x-1)*m+y-1]];
int tempy=y;
while(x>0){
y=tempy;
while(y>0){
rets+=sum[(x-1)*m+y-1];
retc+=cnt[(x-1)*m+y-1];
y-=lowbit(y);
}
x-=lowbit(x);
}
if(rets==retc*tmp) return true;
else return false;
}
void init(){
for(int i=0;i<maxn;i++){
ran[i]=rand();
}
}
int main(){
init();
while(scanf("%d%d%d",&n,&m,&t)==3){
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%d",&a[i*m+j]);
}
}
for(int i=0;i<t;i++){
scanf("%d%d%d%d%d",&x,&y,&z,&w,&k);
update(z+1,w+1,ran[k],1);
update(x,y,ran[k],1);
update(x,w+1,-ran[k],-1);
update(z+1,y,-ran[k],-1);
}
int ans=n*m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
if(query(i,j)) ans--;
}
printf("%d\n",ans);
}
return 0;
}