吐槽一下,好啃的题目。。。。。
我们可以看到在两个点之间的矩形内分界线是直线x+y+C=0或x-y+C=0。矩形之外都是矩形的分界线。
然后思路很明显了,我们将要询问的矩形全记下来,最后用扫描线加树状数组求答案即可。
程序。。。。还是贴上来吧
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int Maxn=100005;
#define lowbit(x) ((x)&(-(x)))
int n,m,z,p,i,j,x0,x1,y0,y1,tot[3];
int px,py,qx,qy,l,r,N,mid,tr[Maxn],a[Maxn],b[Maxn],ANS[Maxn][2];
struct arr
{
int x,y0,y1,num;
bool flag;
void make(int X,int Y0,int Y1,bool Flag,int NUM)
{ x=X; y0=Y0; y1=Y1; flag=Flag; num=NUM; }
bool operator <(const arr &a)const
{ return x<a.x; }
}Qy[3][Maxn*6];
struct Point
{
int x,y;
bool operator <(const Point &a)const
{ return x<a.x||(x==a.x&&y<a.y); }
} dot[Maxn];
void work0(int K){ //x1>x0 y1>y0
if (x1-x0==y1-y0){
Qy[0][tot[0]++].make(x0, 1,y1-1,1,i*100+K);
Qy[0][tot[0]++].make(n, y0+1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(x1-1,y0+1,m,0,i*100+(K^1));
Qy[1][tot[1]++].make(x1-1,1,x1+y0-1,1,i*100+K);
Qy[1][tot[1]++].make(x0, 1,x1+y0-1,0,i*100+K);
Qy[1][tot[1]++].make(x1-1,x1+y0+1,n+m,1,i*100+(K^1));
Qy[1][tot[1]++].make(x0, x1+y0+1,n+m,0,i*100+(K^1));
} else
if (x1-x0>y1-y0){
px=(x0+x1+y0-y1)/2;
qx=(x0+x1+y1-y0)/2;
if ( (x0+x1+y0-y1)&1 ){
Qy[0][tot[0]++].make(px,1,m,1,i*100+K);
Qy[0][tot[0]++].make(n, 1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(qx,1,m,0,i*100+(K^1));
Qy[1][tot[1]++].make(qx,1,px+y1,1,i*100+K);
Qy[1][tot[1]++].make(px,1,px+y1,0,i*100+K);
Qy[1][tot[1]++].make(qx,px+y1+1,n+m,1,i*100+(K^1));
Qy[1][tot[1]++].make(px,px+y1+1,n+m,0,i*100+(K^1));
} else
{
Qy[0][tot[0]++].make(px-1,y1,m,1,i*100+K);
Qy[0][tot[0]++].make(px,1,y1-1,1,i*100+K);
Qy[0][tot[0]++].make(n, 1,y0,1,i*100+(K^1));
Qy[0][tot[0]++].make(qx, 1,y0,0,i*100+(K^1));
Qy[0][tot[0]++].make(n, y0+1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(qx-1,y0+1,m,0,i*100+(K^1));
Qy[1][tot[1]++].make(qx-1,1,px+y1-1,1,i*100+K);
Qy[1][tot[1]++].make(px, 1,px+y1-1,0,i*100+K);
Qy[1][tot[1]++].make(qx-1,px+y1+1,n+m,1,i*100+(K^1));
Qy[1][tot[1]++].make(px, px+y1+1,n+m,0,i*100+(K^1));
}
} else
if (x1-x0<y1-y0){
py=(y0+y1+x1-x0)/2;
qy=(y0+y1+x0-x1)/2;
if ( (y0+y1+x1-x0)&1 ){
Qy[0][tot[0]++].make(x0,1,py,1,i*100+K);
Qy[0][tot[0]++].make(n, 1,qy,1,i*100+K);
Qy[0][tot[0]++].make(x1,1,qy,0,i*100+K);
Qy[0][tot[0]++].make(x0,py+1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(n, qy+1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(x1,qy+1,m,0,i*100+(K^1));
Qy[1][tot[1]++].make(x1,1,py+x0,1,i*100+K);
Qy[1][tot[1]++].make(x0,1,py+x0,0,i*100+K);
Qy[1][tot[1]++].make(x1,py+x0+1,n+m,1,i*100+(K^1));
Qy[1][tot[1]++].make(x0,py+x0+1,n+m,0,i*100+(K^1));
} else
{
Qy[0][tot[0]++].make(x0,1,py-1,1,i*100+K);
Qy[0][tot[0]++].make(n, 1,qy-1,1,i*100+K);
Qy[0][tot[0]++].make(x1,1,qy-1,0,i*100+K);
Qy[0][tot[0]++].make(x0,py+1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(n, qy+1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(x1,qy+1,m,0,i*100+(K^1));
Qy[1][tot[1]++].make(x1,1,py+x0-1,1,i*100+K);
Qy[1][tot[1]++].make(x0,1,py+x0-1,0,i*100+K);
Qy[1][tot[1]++].make(x1,py+x0+1,n+m,1,i*100+(K^1));
Qy[1][tot[1]++].make(x0,py+x0+1,n+m,0,i*100+(K^1));
}
}
}
void work1(int K){ //x1>x0 y0>y1
if (x1-x0==y0-y1){
Qy[0][tot[0]++].make(x0, y1+1,m,1,i*100+K);
Qy[0][tot[0]++].make(n, 1,y0-1,1,i*100+(K^1));
Qy[0][tot[0]++].make(x1-1,1,y0-1,0,i*100+(K^1));
Qy[2][tot[2]++].make(x1-1,-m,x0-y1-1,1,i*100+K);
Qy[2][tot[2]++].make(x0, -m,x0-y1-1,0,i*100+K);
Qy[2][tot[2]++].make(x1-1, x0-y1+1,n,1,i*100+(K^1));
Qy[2][tot[2]++].make(x0, x0-y1+1,n,0,i*100+(K^1));
} else
if (x1-x0>y0-y1){
px=(x0+x1+y1-y0)/2;
qx=(x0+x1+y0-y1)/2;
if ( (x0+x1+y1-y0)&1 ){
Qy[0][tot[0]++].make(px,1,m,1,i*100+K);
Qy[0][tot[0]++].make(n, 1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(qx,1,m,0,i*100+(K^1));
Qy[2][tot[2]++].make(qx,-m,qx-y0,1,i*100+K);
Qy[2][tot[2]++].make(px,-m,qx-y0,0,i*100+K);
Qy[2][tot[2]++].make(qx,qx-y0+1,n,1,i*100+(K^1));
Qy[2][tot[2]++].make(px,qx-y0+1,n,0,i*100+(K^1));
} else
{
Qy[0][tot[0]++].make(px-1,1,y1,1,i*100+K);
Qy[0][tot[0]++].make(px,y1+1,m,1,i*100+K);
Qy[0][tot[0]++].make(n, y0,m,1,i*100+(K^1));
Qy[0][tot[0]++].make(qx, y0,m,0,i*100+(K^1));
Qy[0][tot[0]++].make(n, 1,y0-1,1,i*100+(K^1));
Qy[0][tot[0]++].make(qx-1,1,y0-1,0,i*100+(K^1));
Qy[2][tot[2]++].make(qx-1,-m,qx-y0-1,1,i*100+K);
Qy[2][tot[2]++].make(px, -m,qx-y0-1,0,i*100+K);
Qy[2][tot[2]++].make(qx-1,qx-y0+1,n,1,i*100+(K^1));
Qy[2][tot[2]++].make(px, qx-y0+1,n,0,i*100+(K^1));
}
} else
{
py=(y0+y1+x0-x1)/2;
qy=(y0+y1+x1-x0)/2;
if ( (y0+y1+x1-x0)&1 ){
Qy[0][tot[0]++].make(x0,py+1,m,1,i*100+K);
Qy[0][tot[0]++].make(n, qy+1,m,1,i*100+K);
Qy[0][tot[0]++].make(x1,qy+1,m,0,i*100+K);
Qy[0][tot[0]++].make(x0,1,py,1,i*100+(K^1));
Qy[0][tot[0]++].make(n, 1,qy,1,i*100+(K^1));
Qy[0][tot[0]++].make(x1,1,qy,0,i*100+(K^1));
Qy[2][tot[2]++].make(x1,-m,x0-py-1,1,i*100+K);
Qy[2][tot[2]++].make(x0,-m,x0-py-1,0,i*100+K);
Qy[2][tot[2]++].make(x1,x0-py,n,1,i*100+(K^1));
Qy[2][tot[2]++].make(x0,x0-py,n,0,i*100+(K^1));
} else
{
Qy[0][tot[0]++].make(x0,py+1,m,1,i*100+K);
Qy[0][tot[0]++].make(n, qy+1,m,1,i*100+K);
Qy[0][tot[0]++].make(x1,qy+1,m,0,i*100+K);
Qy[0][tot[0]++].make(x0,1,py-1,1,i*100+(K^1));
Qy[0][tot[0]++].make(n, 1,qy-1,1,i*100+(K^1));
Qy[0][tot[0]++].make(x1,1,qy-1,0,i*100+(K^1));
Qy[2][tot[2]++].make(x1,-m,x0-py-1,1,i*100+K);
Qy[2][tot[2]++].make(x0,-m,x0-py-1,0,i*100+K);
Qy[2][tot[2]++].make(x1,x0-py+1,n,1,i*100+(K^1));
Qy[2][tot[2]++].make(x0,x0-py+1,n,0,i*100+(K^1));
}
}
}
void work2(int K){
if ( (y0+y1)&1 ){
Qy[0][tot[0]++].make(n,1,(y0+y1)/2,1,i*100+K);
Qy[0][tot[0]++].make(n,(y0+y1)/2+1,m,1,i*100+(K^1));
} else
{
Qy[0][tot[0]++].make(n,1,(y0+y1)/2-1,1,i*100+K);
Qy[0][tot[0]++].make(n,(y0+y1)/2+1,m,1,i*100+(K^1));
}
}
void work3(int K){
if ( (x0+x1)&1 ){
Qy[0][tot[0]++].make((x0+x1)/2,1,m,1,i*100+K);
Qy[0][tot[0]++].make(n,1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make((x0+x1)/2,1,m,0,i*100+(K^1));
} else
{
Qy[0][tot[0]++].make((x0+x1)/2-1,1,m,1,i*100+K);
Qy[0][tot[0]++].make(n,1,m,1,i*100+(K^1));
Qy[0][tot[0]++].make((x0+x1)/2,1,m,0,i*100+(K^1));
}
}
int low(int x){
int ret=N+1;
l=1; r=N;
while (l<=r){
mid=(l+r)>>1;
if (a[mid]>=x) ret=mid,r=mid-1;
else l=mid+1;
}
return ret;
}
int up(int x){
int ret=0;
l=1; r=N;
while (l<=r){
mid=(l+r)>>1;
if (a[mid]<=x) ret=mid,l=mid+1;
else r=mid-1;
}
return ret;
}
void add(int x){
for (int i=x;i<=N;i+=lowbit(i))
tr[i]++;
}
int query(int x){
int ret=0;
for (int i=x;i>0;i-=lowbit(i))
ret+=tr[i];
return ret;
}
int query(int l,int r){
if (l>r) return 0;
return query(r)-query(l-1);
}
void calc(int K){
memset(tr,0,sizeof(tr));
sort(Qy[K],Qy[K]+tot[K]);
for (i=0;i<tot[K];i++){
Qy[K][i].y0=low(Qy[K][i].y0);
Qy[K][i].y1=up(Qy[K][i].y1);
}
for (i=1,j=0;i<=z;i++){
for (;j<tot[K]&&Qy[K][j].x<dot[i].x;j++){
int tmp=query(Qy[K][j].y0,Qy[K][j].y1);
if (Qy[K][j].flag) ANS[Qy[K][j].num/100][Qy[K][j].num%100]+=tmp;
else ANS[Qy[K][j].num/100][Qy[K][j].num%100]-=tmp;
}
add(b[i]);
while (i<z && dot[i+1].x==dot[i].x)
add(b[++i]);
}
for (;j<tot[K];j++){
int tmp=query(Qy[K][j].y0,Qy[K][j].y1);
if (Qy[K][j].flag) ANS[Qy[K][j].num/100][Qy[K][j].num%100]+=tmp;
else ANS[Qy[K][j].num/100][Qy[K][j].num%100]-=tmp;
}
}
void calc(){
for (i=1;i<=z;i++) a[i]=dot[i].y;
sort(a+1,a+z+1);
N=unique(a+1,a+z+1)-a-1;
for (i=1;i<=z;i++) b[i]=lower_bound(a+1,a+N+1,dot[i].y)-a;
calc(0);
for (i=1;i<=z;i++) a[i]=dot[i].x+dot[i].y;
sort(a+1,a+z+1);
N=unique(a+1,a+z+1)-a-1;
for (i=1;i<=z;i++) b[i]=lower_bound(a+1,a+N+1,dot[i].x+dot[i].y)-a;
calc(1);
for (i=1,j=0;i<=z;i++) a[i]=dot[i].x-dot[i].y;
sort(a+1,a+z+1);
N=unique(a+1,a+z+1)-a-1;
for (i=1;i<=z;i++) b[i]=lower_bound(a+1,a+N+1,dot[i].x-dot[i].y)-a;
calc(2);
}
int main(){
scanf("%d%d%d%d",&n,&m,&z,&p);
for (i=1;i<=z;i++)
scanf("%d%d",&dot[i].x,&dot[i].y);
sort(dot+1,dot+z+1);
for (i=1;i<=p;i++){
scanf("%d%d",&x0,&y0);
scanf("%d%d",&x1,&y1);
if (x0==x1){
if (y0<y1) work2(0);
else
{
swap(y1,y0);
work2(1);
}
continue;
}
if (y0==y1){
if (x0<x1) work3(0);
else
{
swap(x1,x0);
work3(1);
}
continue;
}
if (x0<x1&&y0<y1) work0(0);
else if (x1<x0&&y1<y0){
swap(x0,x1);
swap(y0,y1);
work0(1);
}
else if (x0<x1&&y1<y0) work1(0);
else if (x1<x0&&y0<y1){
swap(x0,x1);
swap(y0,y1);
work1(1);
}
}
calc();
for (i=1;i<=p;i++)
printf("%d %d %d\n",ANS[i][0],ANS[i][1],z-ANS[i][0]-ANS[i][1]);
return 0;
}