hdu5091(扫描线+线段树)

本文介绍了一个利用扫描线和线段树解决矩形覆盖最多点数问题的方法。通过将坐标转换为非负数,并在y轴上建立线段树,可以有效地计算出矩形能够覆盖的最大点数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给n个点,和长w宽h的矩形,问矩形最多能包含多少个点。

思路:扫描线+线段树,首先将坐标转化成非负数,对于每个点(x,y),标记为1,生成一个(x+w,y)的点,标记为-1,然后将y轴建立线段树,维护一个最大值即可。如不不明白的话,画个图,理解一下就好了。

代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<stdio.h>
#include<math.h>
#define N 20000
#define inf 0x7ffffff
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
struct node
{
    int x,y,flag;
}s[2*N+5];
bool cmp(node a,node b)
{
    if(a.x != b.x)  return a.x < b.x;
    //if(a.flag != b.flag)
    return  a.flag > b.flag;
}
struct tree
{
    int l,r,flag,maxx;
}tree[4*2*N];
void build(int o,int l,int r)
{
    tree[o].l = l;
    tree[o].r = r;
    tree[o].maxx = tree[o].flag = 0;
    if(l == r)  return ;
    int m = (l+r)/2;
    build(2*o,l,m);
    build(2*o+1,m+1,r);
}
void pushup(int o)
{
    tree[o].maxx = max(tree[2*o].maxx, tree[2*o+1].maxx );
}
void pushdown(int o)
{
    if(tree[o].flag != 0)
    {
        tree[2*o].flag += tree[o].flag;
        tree[2*o+1].flag += tree[o].flag;
        tree[2*o].maxx += tree[o].flag;
        tree[2*o+1].maxx += tree[o].flag;
        tree[o].flag = 0;
    }
}
void update(int o,int x,int y,int v)
{
    if(x <= tree[o].l && tree[o].r <= y)
    {
        tree[o].flag += v;
        tree[o].maxx += v;
        return;
    }
    pushdown(o);
    int m = (tree[o].l + tree[o].r)/2;
    if(x <= m)  update(2*o,x,y,v);
    if(y > m)   update(2*o+1,x,y,v);
    pushup(o);
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
    int n,w,h;
    while(scanf("%d",&n))
    {
        if(n < 0)  break;
        scanf("%d%d",&w,&h);
        int i;
        for(i = 0; i < n; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x += N;
            y += N;
            s[2*i].x = x;
            s[2*i].y = y;
            s[2*i].flag = 1;
            s[2*i+1].x = x+w;
            s[2*i+1].y = y;
            s[2*i+1].flag = -1;
        }
        sort(s,s+2*n,cmp);
        build(1,1,2*N+1);
        int ans = 0;
        for(i = 0; i < 2*n; i++)
        {
            update(1,s[i].y, s[i].y+h ,s[i].flag);
            ans = max(ans,tree[1].maxx);
        }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值