其他分享
首页 > 其他分享> > P2163 [SHOI2007]园丁的烦恼 | 二维数点

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)\)的答案,那么原答案即为:

\[S(c,d) - S(a - 1,d) - S(c,b - 1) + S(a - 1,b - 1) \]

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