【HDU6514】Monitor(二维树状数组)
MonitorTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 163840/163840 K (Java/Others)Total Submission(s): 794 Accepted Submission(s): 251 Problem Description Xiaoteng has a large area of land for growing crops, and the land can be seen as a rectangle of n×m .
Input There are mutiple test cases.
Output For each case you should print q lines.
Sample Input 6 6 3 2 2 4 4 3 3 5 6 5 1 6 2 2 3 2 5 4 1 5 6 5
Sample Output YES NO Hint In the picture,the red solid rectangles mean the monitor Xiaoteng installed, and the blue dotted rectangles mean the area will be stolen.
Source |
【题意】
在一个面积不超过n*m的矩形上,有p个矩形A,问之后的q个矩形B能否被之前的A全部覆盖(每个B的点都在至少一个A中)。
【解题思路】
对于A类矩形(x1,y1,x2,y2),我们只需要在(x1,y1),(x2+1,y2+1)处+1,在(x1,y2+1)(x2+1,y1)处-1。
之后对整个面积求一个前缀和。则大于0的地方就是被A类矩形覆盖的点。 把值大于0的地方变成1,再一次求一次前缀和,处理好后即可在O(1)的时间算出一个矩形内被覆盖的点的数量。
需要注意的是因为n*m<10^7,所以需要把二维转换成一维来做。
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e7+500;
LL a[maxn],s[maxn];
int n,m,p,q;
int lowbit(int x)
{
return (-x)&x;
}
void add(int x,int y,int z)
{
int ty=y;
while(x<=n)
{
y=ty;
while(y<=m)
{
a[x*m+y]+=z;
y+=lowbit(y);
}
x+=lowbit(x);
}
}
LL query(int x,int y)
{
LL sum=0;
int ty=y;
while(x)
{
y=ty;
while(y)
{
sum+=a[x*m+y];
y-=lowbit(y);
}
x-=lowbit(x);
}
return sum;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(a,0,sizeof(a));
memset(s,0,sizeof(s));
int x1,y1,x2,y2;
scanf("%d",&p);
while(p--)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
add(x1,y1,1);
add(x1,y2+1,-1);
add(x2+1,y1,-1);
add(x2+1,y2+1,1);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int t=query(i,j);
if(t>0)s[i*m+j]=1;
else s[i*m+j]=0;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
s[i*m+j]+=s[(i-1)*m+j]+s[i*m+j-1]-s[(i-1)*m+j-1];
}
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
LL t1=(x2-x1+1)*(y2-y1+1);
LL t2=s[x2*m+y2]+s[(x1-1)*m+y1-1]-s[(x1-1)*m+y2]-s[x2*m+y1-1];
if(t1==t2)printf("YES\n");
else printf("NO\n");
}
}
}
推荐阅读