P2163 [SHOI2007]园丁的烦恼 | 二维数点
作者:互联网
说在前面
这题有点卡常...
Problem
给定\(n\)个点\(P_i(x_i,y_i)\),每次给一个矩形(给定左下角\((a,b)\)和右上角\((c,d)\)),求这个矩形里有多少个点。
\(1 \le n,m \le 5 \times 10^5,0 \le x_i,y_i,a,b,c,d \le 10^7\).
Solution
Thinking 1
发现有矩形查询,考虑二维数据结构二维前缀和,然而坐标范围太大,开不了。
Thinking 2
发现有矩形查询,然后还是求和这种可叠加和删除的东西,可以用二维前缀和类似的方法:
设\(S(x,y)\)为对应\((0,0) \to (x,y)\)的答案,那么原答案即为:
Thinking 3
发现求解\(S(x,y)\)就是求\(\sum [x_i \le x][y_i \le y]\),这不直接排序+BIT过去?
然后就没了。
# include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
// map <pair<int,int> ,int> f;
int n,m;
int b[N << 2];
int c[N << 2];
int tot = 0;
int f[N << 2];
struct Point
{
int x,y;
int ans,id;
Point() {}
Point(int _x,int _y) : x(_x),y(_y) {}
}P[N],Q[N << 2];
int totx = 0,toty = 0;
struct Matrix
{
Point P1,P2;
}A[N];
template <typename T> void read(T &x)
{
x = 0;int w = 1;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') w = -1;
ch = getchar();
}
while(isdigit(ch))
{
x = x * 10 + ch - '0';
ch = getchar();
}
x *= w;
return;
}
void write(int x)
{
if(x < 0) putchar('-'),x = -x;
if(x >= 10) write(x / 10);
char ch = (x % 10) + 48;
putchar(ch);
return;
}
int Lx,Ly;
struct BIT
{
int T[N * 3];
int lowbit(int x) {return x & (-x);}
void add(int x,int d)
{
while(x <= Ly + 1)
{
T[x] += d;
x += lowbit(x);
}
return;
}
int query(int x)
{
int total = 0;
while(x)
{
total += T[x];
x -= lowbit(x);
}
return total;
}
}T;
bool compare(const struct Point &x,const struct Point &y) {return (x.x == y.x) ? x.y < y.y : x.x < y.x;}
void Read_Point(Point &x) {read(x.x),read(x.y);}
int main(void)
{
read(n),read(m);
for(register int i = 1; i <= n; i++)
{
Read_Point(P[i]);
b[++totx] = P[i].x,c[++toty] = P[i].y;
}
for(register int i = 1; i <= m; i++)
{
Read_Point(A[i].P1),Read_Point(A[i].P2);
int x1 = A[i].P1.x,x2 = A[i].P2.x,y1 = A[i].P1.y,y2 = A[i].P2.y;
Q[i] = Point(x2,y2),Q[i].id = i;
Q[m + i] = Point(x1 - 1,y2),Q[m + i].id = m + i;
Q[2 * m + i] = Point(x2,y1 - 1),Q[2 * m + i].id = 2 * m + i;
Q[3 * m + i] = Point(x1 - 1,y1 - 1),Q[3 * m + i].id = 3 * m + i;
tot += 4;
}
for(register int i = 1; i <= tot; i++) b[++totx] = Q[i].x,c[++toty] = Q[i].y;
sort(b + 1, b + totx + 1);
sort(c + 1, c + toty + 1);
Lx = unique(b + 1, b + totx + 1) - b - 1;
Ly = unique(c + 1, c + toty + 1) - c - 1;
for(register int i = 1; i <= n; i++)
{
P[i].x = lower_bound(b + 1, b + Lx + 1, P[i].x) - b + 1;
P[i].y = lower_bound(c + 1, c + Ly + 1, P[i].y) - c + 1;
}
for(register int i = 1; i <= tot; i++)
{
Q[i].x = lower_bound(b + 1, b + Lx + 1, Q[i].x) - b + 1;
Q[i].y = lower_bound(c + 1, c + Ly + 1, Q[i].y) - c + 1;
}
for(register int i = 1; i <= m; i++)
{
A[i].P1.x = lower_bound(b + 1, b + Lx + 1, A[i].P1.x) - b + 1;
A[i].P2.x = lower_bound(b + 1, b + Lx + 1, A[i].P2.x) - b + 1;
A[i].P1.y = lower_bound(c + 1, c + Ly + 1, A[i].P1.y) - c + 1;
A[i].P2.y = lower_bound(c + 1, c + Ly + 1, A[i].P2.y) - c + 1;
}
sort(P + 1, P + n + 1, compare);
sort(Q + 1, Q + tot + 1, compare);
for(int i = 1; i <= tot; i++) f[Q[i].id] = i;
int j = 1;
for(register int i = 1; i <= tot; i++)
{
while(j <= n && P[j].x <= Q[i].x) T.add(P[j].y,1),++j;
Q[i].ans = T.query(Q[i].y);
// printf("Q[%d].ans = %d\n",i,Q[i].ans);
}
for(register int i = 1; i <= m; i++)
{
int x1 = A[i].P1.x,x2 = A[i].P2.x,y1 = A[i].P1.y,y2 = A[i].P2.y;
// printf("query : (%d,%d),(%d,%d),(%d,%d),(%d,%d)\n",x2,y2,x1 - 1,y2,x2,y1 - 1,x1 - 1,y1 - 1);
int a1 = Q[f[i]].ans - Q[f[m + i]].ans - Q[f[2 * m + i]].ans + Q[f[3 * m + i]].ans;
write(a1),putchar('\n');
}
return 0;
}
标签:10,ch,int,数点,P2163,二维,le,SHOI2007,矩形 来源: https://www.cnblogs.com/luyiming123blog/p/14779069.html