题目大意:二维平面上,有 q 个操作,每个操作有两种类型:
1:在(x,y)坐标添加一个点
2:添加一个矩形区域:左下角是(x1,y1),右上角是(x2,y2)
对于每一个操作,输出有多少个pair:(矩形区域,点对) ,点对被包含在矩形区域中。
如果当前操作是添加一个矩形区域,答案 = 前面所有矩形区域的答案之和 + 当前矩形区域包括的点的个数。
如果当前操作是添加一个点,答案 = 前面所有的矩形区域的答案之和 + 当前点被包括在的矩形区域的个数。
实际上就是将答案求和,输出。
需要计算一个点被几个矩形区域包含和一个矩形区域包含几个点,用CDQ分治分类处理,矩形包含点的问题比较好处理,就是CDQ三维偏序裸题。
点被矩形包含要变换一下,因为矩形被拆成了4个点,如果一个点被一个矩形包含,那么这个矩形被拆出来的4个点中只有左下角(x,y) 满足 x < x1,y < y1。(可以在图上画,分类讨论点和矩形的相对位置的情况,寻找特征性质。
根据这个CDQ分治即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define lowbit(i) (i & (-i))
const int maxn = 1e6 + 10;
typedef long long ll;
int q;
struct node{
int x,y,op,id;
node(int xi = 0,int yi = 0,int pi = 0,int di = 0) {
x = xi; y = yi; op = pi; id = di;
}
}qes[maxn],tmp[maxn];
int c[maxn],t,p,cnt,top;
ll val[maxn],ans[maxn];
void init() {
sort(c + 1,c + t + 1);
p = unique(c + 1,c + t + 1) - c - 1;
}
int Hash(int x) {
return lower_bound(c + 1,c + p + 1,x) - c;
}
void upd(int p,int v) {
for(int i = p; i < maxn; i += lowbit(i))
val[i] += v;
}
int qry(int x) {
int ans = 0;
for(int i = x; i; i -= lowbit(i))
ans += val[i];
return ans;
}
void cdq(int l,int r) {
if(l >= r) return;
int mid = l + r >> 1;
cdq(l,mid);cdq(mid + 1,r);
top = 0;
for(int i = l,j = mid + 1; i <= mid || j <= r;) {
if(i <= mid && (j > r || qes[i].x <= qes[j].x)) {
if(qes[i].op == 1) upd(qes[i].y,1);
tmp[++top] = qes[i++];
} else {
if(qes[j].op == 2) {
ans[qes[j].id] += qry(qes[j].y);
} else if(qes[j].op == 3) {
ans[qes[j].id] -= qry(qes[j].y);
}
tmp[++top] = qes[j++];
}
}
top = 0;
for(int i = l; i <= mid; i++)
if(qes[i].op == 1) upd(qes[i].y,-1);
for(int i = l,j = mid + 1; i <= mid || j <= r;) {
if(i <= mid && (j > r || qes[i].x < qes[j].x)) {
if(qes[i].op == 2) upd(qes[i].y,1);
else if(qes[i].op == 3) upd(qes[i].y,-1);
tmp[++top] = qes[i++];
} else {
if(qes[j].op == 1) ans[qes[j].id] += qry(qes[j].y - 1);
tmp[++top] = qes[j++];
}
}
for(int i = l; i <= mid; i++) {
if(qes[i].op == 2) upd(qes[i].y,-1);
else if(qes[i].op == 3) upd(qes[i].y,1);
}
for(int i = l; i <= r; i++)
qes[i] = tmp[i - l + 1];
}
int main() {
scanf("%d",&q);
for(int i = 1; i <= q; i++) {
int type,x1,y1,x2,y2;
scanf("%d",&type);
if(type == 1) {
scanf("%d%d",&x1,&y1);
c[++t] = x1,c[++t] = y1;
qes[++cnt] = node(x1,y1,1,i);
} else {
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
qes[++cnt] = node(x1 - 1,y1 - 1,2,i);
qes[++cnt] = node(x2,y2,2,i);
qes[++cnt] = node(x1 - 1,y2,3,i);
qes[++cnt] = node(x2,y1 - 1,3,i);
c[++t] = x1 - 1,c[++t] = y1 - 1,c[++t] = x2,c[++t] = y2;
}
}
init();
for(int i = 1; i <= cnt; i++) {
qes[i].x = Hash(qes[i].x);
qes[i].y = Hash(qes[i].y);
}
cdq(1,cnt);
for(int i = 1; i <= q; i++) {
ans[i] += ans[i - 1];
printf("%lld\n",ans[i]);
}
return 0;
}
/*
5
1 2 3
1 2 2
1 3 4
2 1 1 5 5
2 2 2 2 2
*/