[BZOJ 1120]POI2009 str

吐槽一下,好啃的题目。。。。。

我们可以看到在两个点之间的矩形内分界线是直线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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值