【扫描线&&线段树&&矩阵范围内点个数】HDU - 5091

Step1 Problem:

平面上有n个点(x, y), 你有一个宽W, 高H的框,问你一次最多可以框到几个点(包括框的边界)。

Step2 Ideas:

对于每个点(x, y),我们维护一个右上方的矩阵【(x, y) -> (x+w, y+h)】
对于每个点(x, y),你另外添加一个点(x+w, y)。从左到右扫描:遇到(x, y),区间[y, y+h]加1,遇到(x+w, y),区间[y, y+h]减1。
区间更新 用线段树维护。对于每次更新求 区间最大值即可。

Step3 Code:

#include<bits/stdc++.h>
using namespace std;
#define lson root<<1
#define rson root<<1|1
#define MID int mid = (l+r)/2
const int N = 1e4+100;
struct Node
{
    int x, y, val;
    bool operator < (const Node &b) const {
        if(x == b.x) return val > b.val;
        else return x < b.x;
    }
};
struct node
{
    int data, lazy;
};
int w, h;
Node b[N*2];
node a[N*4*4];
void updown(int root)
{
    if(a[root].lazy)
    {
        a[lson].lazy += a[root].lazy;
        a[rson].lazy += a[root].lazy;
        a[lson].data += a[root].lazy;
        a[rson].data += a[root].lazy;
        a[root].lazy = 0;
    }
}
void updata(int root, int l, int r, int pos)
{
    if(b[pos].y <= l && r <= b[pos].y + h)
    {
        a[root].lazy += b[pos].val;
        a[root].data += b[pos].val;
        return ;
    }
    updown(root);
    MID;
    if(mid >= b[pos].y) updata(lson, l, mid, pos);
    if(mid < b[pos].y + h) updata(rson, mid+1, r, pos);
    a[root].data = max(a[lson].data, a[rson].data);
}
int main()
{
    int n, x, y;
    while(~scanf("%d", &n) && ~n)
    {
        scanf("%d %d", &w, &h);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d %d", &x, &y);
            b[i*2-1] = (Node){x, y+2*N, 1};
            b[i*2] = (Node){x+w, y+2*N, -1};
        }
        sort(b+1, b+2*n+1);
        memset(a, 0, sizeof(a));
        int ans = 0;
        for(int i = 1; i <= 2*n; i++)
        {
            updata(1, 1, 4*N, i);
            ans = max(ans, a[1].data);
        }
        printf("%d\n", ans);
    }
}

猜你喜欢

转载自blog.csdn.net/bbbbswbq/article/details/80164590
今日推荐