Comet OJ 茶颜悦色 线段树+扫描线(矩形覆盖最多点+优化)

题目:https://www.cometoj.com/contest/59/problem/D?problem_id=2713

题意:给你一个正方形,然后给你n个点,这个正方形能随意放哪,要求那个正方形能覆盖的最多点是多少个

思路:我们其实可以把题目转换一下,我们可以以每个点为中心,我们就可以以那个点+正方形边长,就代表正方形在这个范围内就能覆盖到当前点

然后我们就相当与求一个点被覆盖的最多次数是多少,我们利用扫描线,我们每次入边加进去,然后我们求区间最大值来持续更新即可,因为如果一点

值为3就代表被三个正方形所覆盖,那么选择这个位置就能盖三个点

 

#include<bits/stdc++.h>
#define maxn 400005
#define mod 1000000007 
#define ld (d<<1)
#define rd (d<<1|1)
using namespace std;
typedef long long ll;
struct sss
{
    ll l,r,h;
    ll val; 
    sss(){};
    sss(ll a,ll b,ll c,ll d){
        l=a;
        r=b;
        h=c;
        val=d;
    };
}ss[maxn*4];
ll X[maxn*4];
ll n,k;
ll num;
int cmp(struct sss x,struct sss y){
    if(x.h==y.h) return x.val>y.val;
    return x.h<y.h;
}
ll sum[maxn*4],cnt[4*maxn];
ll xx[maxn];
void push_up(int id)
{
    sum[id]=max(sum[id*2],sum[id*2+1])+cnt[id];
    return ;
}
void modify(int ql,int qr,int flag,int l,int r,int id)
{
    //cout<<ql<<" "<<qr<<" "<<l<<" "<<r<<endl;
    if(ql<=l&&r<=qr)
    {
        sum[id]+=flag;
        cnt[id]+=flag;
        //push_up(id);
        return ;
    }
    int mid=(l+r)/2;
    if(ql<=mid)
    {
        modify(ql,qr,flag,l,mid,2*id);
    }
    if(qr>mid)
    {
        modify(ql,qr,flag,mid+1,r,2*id+1);
    }
    push_up(id);
    return ;
}
int main(){
    scanf("%lld%lld",&n,&k);
    ll x,y;
    for(int i=0;i<n;i++){
        scanf("%lld%lld",&x,&y);
        X[num]=x;
        ss[num++]=sss(x,x+k,y,(ll)1);
        X[num]=x+k;
        ss[num++]=sss(x,x+k,y+k,(ll)(-1));
    }
    sort(ss,ss+num,cmp);
    sort(X,X+num);
    int m=unique(X,X+num)-X;
    ll mx=0;
    for(int i=0;i<num;i++){
        int l=lower_bound(X,X+m,ss[i].l)-X;
        int r=lower_bound(X,X+m,ss[i].r)-X;
        if(l<=r)
            modify(l,r,ss[i].val,0,m-1,1);
        mx = max(mx,sum[1]);
    }
    printf("%lld",mx);
}

 

转载于:https://www.cnblogs.com/Lis-/p/11279390.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值