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.
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的农田,里面有很多种植物,由植物编号代替,T个农药,每个农药有一个喷洒区域和一个植物编号,代表只能喷洒这种植物
,如果农药不同于植物的编号,那么这个植物就会死亡,最后求农田里面死亡的植物数量
思路:我们看到了喷洒的是一个矩阵,如果我们是暴力肯定会超时,我们就可以想优化方法,有什么是同时操作一个矩阵里的东西的呢,我们就可以想到,树状数组
树状数组可以操作一个区间,二维树状数组就可以操作一个矩阵,又因为他是操作一个矩阵,所以是区间修改,单点查询的板子,其中用到了差分的概念,但是同时喷洒的我们又可能重复记录
这时我们就可以记录植物所在的位置,具体看代码注释
这里给篇大佬博客 二维树状数组:https://blog.csdn.net/z309241990/article/details/9615259
#include<cstdio> #include<cmath> #include<cstring> #include<vector> #include<algorithm> #define NN 1000010 using namespace std; struct sss { int x,y; sss(){}; sss(int a,int b){x=a;y=b;}; }; struct node { int x1,y1; int x2,y2; node(int a,int b,int c,int d){x1=a;y1=b;x2=c;y2=d;}; }; vector<sss> mp[NN]; vector<int> c[NN]; vector<node> z[NN]; int n,m,k; int lowbit(int x) { return x&(-x); } void add(int x,int y,int num) { for(int i=x;i<=n;i+=lowbit(i)) { for(int j=y;j<=m;j+=lowbit(j)) { c[i][j]+=num; } } } int sum(int x,int y) { int num=0; for(int i=x;i>0;i-=lowbit(i)) { for(int j=y;j>0;j-=lowbit(j)) { num+=c[i][j]; } } return num; } void sa(int x1,int y1,int x2,int y2,int num) { add(x1,y1,num); add(x2+1,y1,-num); add(x1,y2+1,-num); add(x2+1,y2+1,num); } int main() { int x; scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++)//因为只给出了n*m的范围,范围无法确定,我们就动态分配空间 { c[i].resize(m+10); } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&x); mp[x].push_back(sss(i,j));//这里存下了每种植物分别的(x,y)坐标 } } int a,b,c,d,e; for(int i=1;i<=k;i++) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&e); z[e].push_back(node(a,b,c,d));//存下了每种农药的喷洒区域 sa(a,b,c,d,1);//我们把洒了农药的区域都加一,这里就应用到了二维树状数组 } int ans=0; for(int i=1;i<=n*m;i++)//因为n*m的格子上每个植物可能都不同,所以我们要从1-n*m所有的都遍历一遍 { if(mp[i].size())//因为他的植物编号可能不同,所以我们判断长度判断是否存在 { for(int j=0;j<z[i].size();j++)//我们先把编号i的植物农药所喷洒的区域全部去掉 { struct node x=z[i][j]; sa(x.x1,x.y1,x.x2,x.y2,-1); } for(int j=0;j<mp[i].size();j++)//我们再判断编号i的植物是否还被喷洒过,如果还有,说明不止被同编号的农药喷洒过,就会死亡,所以计数加1 { struct sss x=mp[i][j]; if(sum(x.x,x.y)) ans++; } for(int j=0;j<z[i].size();j++)//我们再把刚刚减去的区域恢复过来,用同种方法测试其他植物 { struct node x=z[i][j]; sa(x.x1,x.y1,x.x2,x.y2,1); } } } printf("%d",ans); }