题目:http://poj.org/problem?id=3416
题意:给你一些点,之后再给你一些点来建立坐标系,问你一三象限的点个数和二四象限的点个数的差
这个题目我们应该离线处理,考虑建立2个树状数组,一个维护当前坐标系的右边点数目,一个维护左边
首先对点和查询的点进行以x从小到大排序,开始将所有点放入右边
之后开始枚举要查询的点,将在该点左边的数从右边删除并加入左边,然后分别求和算结果
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int N=5e5+5;
struct p
{
int x,y,id;
bool operator <(const p&t) const
{
return x<t.x;
}
};
p a[N],b[N];
int n,m;
int l[N],r[N],ans[N];
void add(int *s,int i,int x)
{
while(i<=500001)
{
s[i]+=x;
i+=i&-i;
}
}
int sum(int *s,int i)
{
int tem=0;
while(i>0)
{
tem+=s[i];
i-=i&-i;
}
return tem;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&b[i].x,&b[i].y);
b[i].id=i;
}
sort(a+1,a+1+n);
sort(b+1,b+1+m);
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(int i=1;i<=n;i++)
add(r,a[i].y+1,1);
int st=1,ed;
for(int i=1;i<=m;i++)
{
for(ed=st;ed<=n;ed++)
if (a[ed].x>b[i].x)
break;
for(int j=st;j<ed;j++)
{
add(r,a[j].y+1,-1);
add(l,a[j].y+1,1);
}
int t=sum(r,500001)-sum(r,b[i].y+1)+sum(l,b[i].y+1);
int tt=sum(l,500001)-sum(l,b[i].y+1)+sum(r,b[i].y+1);
ans[b[i].id]=abs(t-tt);
st=ed;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
if (T) printf("\n");
}
return 0;
}