题目链接:https://cn.vjudge.net/problem/HYSBZ-1935
题意:一个矩阵内给你n个点,q个询问,问你某个子矩阵里点的个数
思路:
CDQ分治模板,三维偏序问题,对于查询,化成四部分,所以数组需要开5倍;
要求(x, y) - (z, zz) 之间的点的个数,可以用1 + 2 + 3 + 4 的面积减去 1 + 2 减去 1 + 3 最后加上多减去的 1 的面积
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 5e5 + 30;
struct node{
int x, y, z;
int val, id, op;
}q[maxn * 5], tmp[maxn * 5];
int ans[maxn * 5], sum[maxn * 5];
bool cmp(node x, node y){
if(x.x != y.x) return x.x < y.x;
else if(x.y != y.y) return x.y < y.y;
return x.z < y.z;
}
int lowbit(int x){
return x & (-x);
}
void add(int x, int val){
if(x == 0) return;
while(x < maxn) {
sum[x]+=val;
x += lowbit(x);
}
}
void del(int x) {
if(x == 0) return;
while(x < maxn) {
sum[x] = 0;
x += lowbit(x);
}
}
int query(int x){
int ans = 0;
while(x) {
ans += sum[x];
x -= lowbit(x);
}
return ans;
}
void CDQ(int l, int r){
if(r - l <= 1) {
return;
}
int mid = l + r >> 1;
CDQ(l, mid);
CDQ(mid, r);
int t1 = l, t2 = mid, cnt = 0;
while(t1 < mid && t2 < r){
if(q[t1].y <= q[t2].y){
if(q[t1].op == 1) add(q[t1].z, q[t1].val);
tmp[cnt++] = q[t1++];
}
else {
if(q[t2].op == 2) ans[q[t2].id] += query(q[t2].z);
else if(q[t2].op == 3) ans[q[t2].id] -= query(q[t2].z);
tmp[cnt++] = q[t2++];
}
}
while(t1 < mid) tmp[cnt++] = q[t1++];
while(t2 < r){
if(q[t2].op == 2) ans[q[t2].id] += query(q[t2].z);
else if(q[t2].op == 3) ans[q[t2].id] -= query(q[t2].z);
tmp[cnt++] = q[t2++];
}
for(int i = 0; i < cnt; i++) {
q[i + l] = tmp[i];
del(tmp[i].z);
}
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++) {
scanf("%d%d", &q[i].y, &q[i].z);
q[i].y++;
q[i].z++;
q[i].x = i;
q[i].op = 1;
q[i].val = 1;
ans[i] = 0;
}
int tot = n;
ans[0] = 0;
for(int i = 1; i <= m; i++) {
int x, y, z, zz;
scanf("%d%d%d%d", &x, &y, &z, &zz);
x++; y++; z++; zz++;
q[tot].id = i; q[tot].op = 2; q[tot].x = tot; q[tot].y = x - 1; q[tot].z = y - 1; q[tot].val = 1; tot++;
q[tot].id = i; q[tot].op = 2; q[tot].x = tot; q[tot].y = z; q[tot].z = zz; q[tot].val = 1; tot++;
q[tot].id = i; q[tot].op = 3; q[tot].x = tot; q[tot].y = x - 1; q[tot].z = zz; q[tot].val = 1; tot++;
q[tot].id = i; q[tot].op = 3; q[tot].x = tot; q[tot].y = z; q[tot].z = y - 1; q[tot].val = 1; tot++;
}
CDQ(0, tot);
for(int i = 1; i <= m; i++) {
printf("%d\n", ans[i]);
}
return 0;
}