题目意思:
有一个n*m的矩形,每个位置有一个数。有T次操作,每次往一个子矩形的每个格子中放入一个数。 求有多少个格子中被放入了至少一个与对应位置不相同的数。 n*m<=1e6,T<=1e6。
题目分析:
对于这个题,因为我们需要处理的是一个矩形区域的问题,因为我们不难想到可以用二维线段树/二维树状数组去做。(但是鉴于线段树常数过大,而这个题还是挺卡时间的,因此最好采用二维树状数组进行解决)。
我们可以考虑这样的一个做法:我们用一个vector存储某一种药可以作用在哪一些点上;再用一个vector存储T种方案中,每一个种类的药所涉及的范围。假设某一点没有被药所覆盖,该点为0,否则该点大于0。则我们在每一种方案浇花的时,我们用二位树状数组在[x1,y1],[x2,y2]这样的二维空间加1,代表被一种药浇到了。
最后就是整个做法的精髓:我们遍历所有的药的种类,先判断是否这种药是否可以作用在某一点上,如果可行,就遍历所有的有该药的花的区间,消除它的影响。然后再遍历所有的以这种药为生的花,判断是否会死(此时如果遍历的结果发现该花所在的区间不为0,即有其他的药作用在这个花的区间了,则代表花必死)。
这样不断的遍历即可获得答案。
具体细节在代码中有所标记。
代码:
#include <bits/stdc++.h>
#define maxn 1000005
using namespace std;
typedef long long ll;
typedef pair<int,int>PLL;
vector<int>bit[maxn];//vector bit是二维树状数组
vector<PLL>a[maxn];//vector a存储的是第i种药所对应的坐标
struct node{
int a,b,c,d;
node(int _a,int _b,int _c,int _d){
a=_a,b=_b,c=_c,d=_d;
}
};
vector<node>q[maxn];//vector q存储的是第i种药品所撒的区间
int n,m,t;
int lowbit(int x){
return x&-x;
}
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;
}
}
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);
}
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;
}
unsigned int read()//读入挂
{
unsigned int ret=0;
char ch=getchar();
while(ch>'9'||ch<'0')ch=getchar();
while(ch>='0'&&ch<='9')
{
ret=ret*10+ch-'0';
ch=getchar();
}
return ret;
}
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;
z=read();
//scanf("%d",&z);
a[z].push_back(make_pair(i,j));
}
}
for(int i=1;i<=t;i++){
int a,b,c,d,k;
a=read(),b=read(),c=read(),d=read(),k=read();
//scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
update(a,b,c,d,1);//将这一片区间置1
q[k].push_back(node(a,b,c,d));
}
int ans=0;
for(int i=1;i<=n*m;i++){//枚举每一种药
if(a[i].size()){//如果有某种花许需要第i种药
for(auto nw:q[i])//遍历所有的有该药的区间,消除它的影响
update(nw.a,nw.b,nw.c,nw.d,-1);
for(auto nw:a[i]){//遍历所有的以这种药为生的花,判断是否会作用
if(query(nw.first,nw.second)) ans++;
}
for(auto nw:q[i])//回复这种药的作用。
update(nw.a,nw.b,nw.c,nw.d,1);
}
}
cout<<ans<<endl;//输出结果!
return 0;
}