题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5480
题目大意:
在一个n*m的棋盘上,有K辆车,每辆车都可以开过他所在的一整行或者是一整列,给出Q个询问,每个询问都会有一个矩形,问这个矩形的每个格子是否都能被车跑过。
思路:
对每辆车所在的行和列进行涂色,然后可以暴力,这样的话在这题上会T。
如果我用树状数组记录下到第i行或者是第j列的前缀和,那么对于区间[l,r]上面,我就可以算出这个区间的值,如果小于x2-x1,表明其中有些行没有被涂色。对于列的判断也是同理。
判断yes的条件就是:只要有行全部被涂满或者列全部被涂满。
代码:
#include<stdio.h>
#include<string.h>
int d[3][100005];
int lowbit(int x)
{
return x&(-x);
}
void update(int i,int x,int n)
{
while(x<=n)
{
d[i][x]++;
x=x+lowbit(x);
}
}
int getsum(int x,int i)
{
int ans=0;
while(x>0)
{
ans=ans+d[i][x];
x=x-lowbit(x);
}
return ans;
}
int main()
{
int i,j,k,T;
int n,m,K,Q;
int x,y,x1,x2,y1,y2,vis1[100005],vis2[100005];
scanf("%d",&T);
while(T--)
{
memset(d,0,sizeof(d));
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
scanf("%d%d%d%d",&n,&m,&K,&Q);
for(i=1;i<=K;i++)
{
scanf("%d%d",&x,&y);
if(!vis1[x]) //注意判重
{update(0,x,n);
vis1[x]=1;
}
if(!vis2[y])
{
vis2[y]=1;
update(1,y,m);
}
}
while(Q--)
{
int a,b;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
a=getsum(x2,0)-getsum(x1-1,0);
b=getsum(y2,1)-getsum(y1-1,1);
if(a<x2-x1+1&&b<y2-y1+1)printf("No\n");
else printf("Yes\n");
}
}
return 0;
}
/*
3
3 4 2 5
1 1
2 3
1 1 3 2
*/