题意
t组 n和m n个硬币的坐标+m个假定中心原点的坐标
求每个中心坐标对应的一三象限和二四象限上硬币数量的差 保证坐标轴上无硬币
思路
对硬币和中心点分别以x轴从小到大sort
建立两棵树状数组 分别表示当前点的左半边 和 右半边 的点的纵坐标
显然,初始所有点的纵坐标记录到 右半边R[]。
按照x坐标从左到右枚举中心点的横坐标 同时修改这一段的点的纵坐标在两个树状数组里的对应值 getsum求ans
accode
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
const int MaxN = 5e4 + 5;
const int MaxNN = 5e5 + 5;
typedef long long LL;
int t,n,m;
struct NODE{
int x,y,id;
}a[MaxN],A[MaxN];
int L[MaxNN],R[MaxNN],ans[MaxN];
bool cmp(NODE P,NODE Q){
return P.x < Q.x;
}
int lowbit(int k){
return k & (-k);
}
void add(int *tree,int k,int ad){
while(k < MaxNN){
tree[k] += ad;
k += lowbit(k);
}
}
LL getsum(int *tree,int k){
LL sum = 0LL;
while(k){
sum += tree[k];
k -= lowbit(k);
}
return sum;
}
int main()
{
scanf("%d",&t);
while(t--){
for(int i = 0;i < MaxNN; i++){
L[i] = 0;
R[i] = 0;
}
scanf("%d %d",&n,&m);
for(int i = 1;i <= n; i++){
scanf("%d %d",&a[i].x,&a[i].y);
a[i].x ++;
a[i].y ++;
}
for(int i = 1;i <= m; i++){
scanf("%d %d",&A[i].x,&A[i].y);
A[i].x++;
A[i].y++;
A[i].id = i;
}
sort(a + 1,a + 1 + n,cmp);
sort(A + 1,A + 1 + m,cmp);
//from the begin (0,0) all point aren't set
//init:
for(int i = 1;i <= n; i++) add(R,a[i].y,1);
int st = 1,j = 1;
for(int i = 1;i <= m; i++){
for(j = st;j <= n; j++){
if(a[j].x > A[i].x) break;
}
//锁定在当前中心坐标左边的点
for(int k = st;k <= j - 1; k++){
add(L,a[k].y,1);//当前中心坐标左边点的 纵坐标
add(R,a[k].y,-1);//右边清掉
}
int one_three = getsum(R,MaxNN - 4) - getsum(R,A[i].y) + getsum(L,A[i].y);
int two_four = getsum(L,MaxNN - 4) - getsum(L,A[i].y) + getsum(R,A[i].y);
ans[A[i].id] = abs(one_three - two_four);
st = j;
}
for(int i = 1;i <= m; i++) printf("%d\n",ans[i]);
if(t)printf("\n");
}
}