luogu P2163 [SHOI2007]园丁的烦恼
题目大意
给出平面上n个点,m个询问,每次询问一个矩阵内的点数
就是二维数点问题
题解
可以先把一个矩阵的询问转换为四个前缀和询问的形式
然后就是二维偏序问题
由于我懒得写树状数组+离散化,于是写了个CDQ分治
code:
#include<bits/stdc++.h>
#define N 4000005
using namespace std;
struct A{
int x, y, id, o;
}a[N], b[N];
int cmp1(A x, A y){
if(x.x != y.x) return x.x < y.x;
if(x.y != y.y) return x.y < y.y;
return x.id < y.id;
}
int n, m, ANS[N];
void cdq(int l, int r){
if(l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid), cdq(mid + 1, r);
int pos = l - 1, ans = 0, t = 0;
for(int i = mid + 1; i <= r; i ++){
if(a[i].id == 0) continue;
while(a[pos + 1].y <= a[i].y && pos + 1 <= mid){
pos ++;
if(a[pos].id == 0) ans ++;
}
ANS[a[i].id] += a[i].o * ans;
}
pos = l;
for(int i = mid + 1; i <= r; i ++){
while(a[pos].y <= a[i].y && pos <= mid) b[++ t] = a[pos ++];
b[++ t] = a[i];
}
for(int i = pos; i <= mid; i ++) b[++ t] = a[i];
for(int i = l; i <= r; i ++) a[i] = b[i - l + 1];
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) scanf("%d%d", &a[i].x, &a[i].y);
int t = n;
for(int i = 1; i <= m; i ++){
int x, y, xx, yy;
scanf("%d%d%d%d", &x, &y, &xx, &yy);
a[++ t].x = xx, a[t].y = yy, a[t].id = i, a[t].o = 1;
a[++ t].x = xx, a[t].y = y - 1, a[t].id = i, a[t].o = - 1;
a[++ t].x = x - 1, a[t].y = yy, a[t].id = i, a[t].o = - 1;
a[++ t].x = x - 1, a[t].y = y - 1, a[t].id = i, a[t].o = 1;
}
sort(a + 1, a + 1 + t, cmp1);
cdq(1, t);
for(int i = 1; i <= m; i ++) printf("%d\n", ANS[i]);
return 0;
}