题目描述:
You have an empty infinite two-dimensional plane and qq queries. There are two types of queries:
•
<
<
1
,
x
,
y
>
>
<< 1, x ,y>>
<<1,x,y>>— add a point with the coordinates
(
x
,
y
)
(x, y)
(x,y) to the plane.
•
<
<
2
,
x
1
,
y
1
,
x
2
,
y
2
>
>
<<2 ,x1 ,y1 ,x2, y2>>
<<2,x1,y1,x2,y2>> — add a rectangle whose lower left corner has the coordinates
(
x
1
,
y
1
)
(x1, y1)
(x1,y1) and the upper right —
(
x
2
,
y
2
)
(x2, y2)
(x2,y2). The area of this rectangle can be zero and a rectangle can degenerate into a point.
Rectangles and points may overlap, that is, there is not guarantee that the figures are distinct.
In addition, to fulfill these queries, after each of them, you need to print the number of pairs of rectangles and points, in which the point lies on the border or inside the rectangle.
题目大意:
二维平面上,两种操作:
1 x y:在(x,y)放一个点
2 x1,y1,x2,y2:放一个左下角为(x1,y1),右上角为(x2,y2)的矩阵。
每次操作之后要求出 所有矩阵包含的点的数目 的总和。
(
x
,
y
<
=
1
e
9
)
(x,y<=1e9)
(x,y<=1e9)
题解:
CDQ分治练习题
每次操作可以统计当前操作对局面的影响:
如果加入矩阵,则统计这个矩阵包含几个点。矩阵包含点可以看成是四个矩阵前缀和的询问。
如果加入点,则统计这个点被多少个矩阵包含。点
(
x
p
,
y
p
)
(x_p,y_p)
(xp,yp)被一个矩阵包含,则只有矩阵的左下角坐标满足条件
x
<
x
p
,
y
<
y
p
x<x_p,y<y_p
x<xp,y<yp,而其他三个点都不满足。
把点和矩阵分开讨论,矩阵是求小于等于的
(
x
,
y
)
(x,y)
(x,y)坐标,点是求小于的
(
x
,
y
)
(x,y)
(x,y)坐标。问题转换成求三维偏序。cdq分治求一下就可以了。
#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) (x&(-x))
#define P pair<int, int>
using namespace std;
const int maxn = 5e5 + 50;
int a[maxn];
int ans[maxn];
void add(int i, int x){while(i < maxn) a[i] += x, i += lowbit(i);return;}
int qry(int i) {int res = 0;while(i) res += a[i], i -= lowbit(i);return res;}
struct node{
int x, y, op, id;
bool operator < (const node& a)const {return id < a.id;}
}e[maxn], temp[maxn];
vector<P> v;
void cdq1(int l, int r)//算点对矩阵的贡献(小于等于)
{
if(r-l<=1) return;
int mid = (r+l)>>1;
cdq1(l, mid); cdq1(mid, r);
int lp = l, rp = mid, o = 0;
while(lp < mid && rp < r){
if(e[lp].x <= e[rp].x){
if(e[lp].op == 1){
add(e[lp].y, 1);
v.push_back(P(e[lp].y, 1));
}
temp[o++] = e[lp++];
}
else{
if(e[rp].op == 2){
ans[e[rp].id] += qry(e[rp].y);
}
else if(e[rp].op == 3) ans[e[rp].id] -= qry(e[rp].y);
temp[o++] = e[rp++];
}
}
while(lp < mid) temp[o++] = e[lp++];
while(rp < r){
if(e[rp].op == 2) ans[e[rp].id] += qry(e[rp].y);
else if(e[rp].op == 3) ans[e[rp].id] -= qry(e[rp].y);
temp[o++] = e[rp++];
}
for(int i = l; i <r; ++i) e[i] = temp[i - l];
for(int i = 0; i < v.size(); ++i) add(v[i].first, -v[i].second);
v.clear(); return;
}
void cdq2(int l, int r)//算矩阵对点的贡献(小于)
{
if(r-l <= 1) return;
int mid = (l+r)>>1;
cdq2(l, mid); cdq2(mid, r);
int lp = l, rp = mid, o = 0;
while(lp < mid && rp < r){
if(e[lp].x < e[rp].x){
if(e[lp].op == 2){
add(e[lp].y, 1); v.push_back(P(e[lp].y, 1));
}
else if(e[lp].op == 3){
add(e[lp].y, -1); v.push_back(P(e[lp].y, -1));
}
temp[o++] = e[lp++];
}
else{
if(e[rp].op == 1){
ans[e[rp].id] += qry(e[rp].y-1);
}
temp[o++] = e[rp++];
}
}
while(lp < mid) temp[o++] = e[lp++];//temp[o++] = e[lp++]写成 = temp[lp++],debug一小时
while(rp < r){
if(e[rp].op == 1) {
ans[e[rp].id] += qry(e[rp].y - 1);
}
temp[o++] = e[rp++];
}
for(int i = l; i < r; ++i) e[i] = temp[i - l];
for(int i = 0; i < v.size(); ++i) add(v[i].first, -v[i].second);
v.clear(); return;
}
int cc[maxn*2];
int num = 0;
int main()
{
int n;scanf("%d", &n);
int idq = 0;
for(int i = 0; i < n; ++i){
int op;scanf("%d", &op);
if(op == 1){
scanf("%d%d", &e[idq].x, &e[idq].y);
cc[++num] = e[idq].x; cc[++num] = e[idq].y;
e[idq].op = 1; e[idq].id = i; idq++;
}
else{
int x1, x2, y1, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
e[idq].op = 2, e[idq].x = x1-1, e[idq].y = y1 - 1, e[idq].id = i, idq++;
e[idq].op = 2, e[idq].x = x2, e[idq].y = y2, e[idq].id = i, idq++;
e[idq].op = 3, e[idq].x = x1-1, e[idq].y = y2, e[idq].id = i, idq++;
e[idq].op = 3, e[idq].x = x2, e[idq].y = y1 - 1, e[idq].id = i, idq++;
cc[++num] = x1-1, cc[++num] = y1 - 1, cc[++num] = x2, cc[++num] = y2;
}
}
sort(cc+1, cc+num+1);
num = unique(cc+1,cc+1+num) - cc - 1;
for(int i = 0; i < idq; ++i){
e[i].x = lower_bound(cc+1,cc+1+num,e[i].x) - cc;
e[i].y = lower_bound(cc+1,cc+1+num,e[i].y) - cc;
}
cdq1(0, idq);
sort(e, e+idq);
cdq2(0, idq);
ll sum = 0;
for(int i = 0; i < n; ++i){
sum += ans[i];
printf("%lld\n", sum);
}
}