链接: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的农田,每一个地上都种着种类为a[i][j]的植物,接下来要进行T次农药喷洒,每次会对左上角为(x1,y1),右下角为(x2,y2)的矩阵喷洒类型为k的农药,如果被喷洒的植物的种类和农药的种类不同(也就是a[i][j]!=k),这个植物就会死掉。问在T次喷洒之后这n*m个植物有多少个死掉了。
题目思路:一个植物死掉的条件是这个植物被喷洒了与它种类不同的农药,那么我们就可以在喷洒的时候先把所有的农药都按范围喷洒上去(对于矩阵内的值加1),然后对于第 i 种植物,我们再将第 i 种农药喷洒效果去除,再查询这个植物是否被其它农药喷洒过(也就是是否大于0),然后再将去除的效果加回去即可,由于植物的种类最多是n*m=1e6种,所以我们可以考虑用vector来存储不同种类植物的坐标和农药的覆盖范围。而矩阵覆盖和删除的操作我们可以借助二维树状数组来完成,时间复杂度大概是(nm+T)log(nm)log(nm)。(大佬们都是用一个log的做法,还得再学习学习,orz...)
具体实现看代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define FIN freopen("in.txt","r",stdin)
#define fuck(x) cout<<"["<<x<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>pii;
const int MX=1e6+7;
int n,m,t;
vector<int>bit[MX];
vector<pii>point[MX];
inline void add(int x,int y,int z){
for(int i=x;i<=n;i+=lowbit(i)){
for(int j=y;j<=m;j+=lowbit(j))
bit[i][j]+=z;
}
}
inline void update(int x1,int Y1,int x2,int y2,int z){
add(x1,Y1,z);add(x2+1,y2+1,z);
add(x1,y2+1,-z);add(x2+1,Y1,-z);
}
inline int query(int x,int y){
int res=0;
for(int i=x;i;i-=lowbit(i)){
for(int j=y;j;j-=lowbit(j))
res+=bit[i][j];
}
return res;
}
struct que{
int a,b,c,d;
};
vector<que>q[MX];
int main(){
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=n;i++) bit[i].resize(m+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int z;
scanf("%d",&z);
point[z].pb(MP(i,j));
}
}
for(int i=1;i<=t;i++){
int a,b,c,d,k;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
update(a,b,c,d,1);
q[k].pb(que{a,b,c,d});
}
int ans=0;
for(int i=1;i<=n*m;i++){
if(point[i].size()){
for(auto nw:q[i])
update(nw.a,nw.b,nw.c,nw.d,-1);
for(auto nw:point[i]){
if(query(nw.fi,nw.se)) ans++;
}
for(auto nw:q[i])
update(nw.a,nw.b,nw.c,nw.d,1);
}
}
printf("%d\n",ans);
return 0;
}