POI 2001 Goldmine 线段树 扫描线

题目链接

http://www.acm.cs.ecnu.edu.cn/problem.php?problemid=1350

http://main.edu.pl/en/archive/oi/8/kop

求平面n个点(n<=15000),用一个 长宽为 s w的矩阵去套,能套到的最多的点数,在边上的点也算

其实跟之前矩形嵌套求面积类似 (POJ的atlantic)用类似扫描线的做法,把点当做边 (y 到  y值+w),插入线段树,这样就维护了y方向,x方向就用类似队列维护,

在距离大于s的时候,就弹出前面的(即线段树移除那条边),一边添加当前边

维护一个值,看从前扫到后,边层数累积的最多的时候即可。

一开始还以为要维护覆盖值,后来发现没用,直接一个d维护积累层数即可。

一开始输入那里没写好EOF,RE了几次,不知道什么原因,改完之后1A

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int N = 100020;
//int cover[N<<2];
int flag[N<<2];
int d[N<<2];
int s,w,n,maxn;
struct node{
    int x,y;
    bool operator < (const node& rhs ) const{
        if (x==rhs.x) return y<rhs.y;
        return x<rhs.x;
    }
}point[15010];
bool input()
{
    maxn=0;
    if (scanf("%d%d",&s,&w)==EOF) return false;
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        scanf("%d%d",&point[i].x,&point[i].y);
        point[i].x+=30000;
        point[i].y+=30000;
        maxn=max(maxn,point[i].y);
    }
    maxn+=w+10;
    return true;
}
void build(int rt,int l,int r)
{
    //cover[rt]=0;
    flag[rt]=0;
    d[rt]=0;
    if (l>=r) return;
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
}
void pushdown(int rt,int l,int r)
{
    if (flag[rt]==0) return;
    int mid=(l+r)>>1;
    //cover[rt<<1]+=flag[rt]*(mid-l+1);
    //cover[rt<<1|1]+=flag[rt]*(r-mid);
    d[rt<<1]+=flag[rt];
    d[rt<<1|1]+=flag[rt];
    flag[rt<<1]+=flag[rt];
    flag[rt<<1|1]+=flag[rt];
    flag[rt]=0;
}
void up(int rt)
{
    //cover[rt]=cover[rt<<1]+cover[rt<<1|1];
    d[rt]=max(d[rt<<1],d[rt<<1|1]);
}
void remove(int L,int R,int rt,int l,int r)
{
    if (L<=l && r<=R){
        //cover[rt]-=(r-l+1);
        d[rt]--;
        flag[rt]+=-1;
        return;
    }
    pushdown(rt,l,r);
    int mid=(l+r)>>1;
    if (L<=mid) remove(L,R,lson);
    if (R>mid) remove(L,R,rson);
    up(rt);
}
void inserts(int L,int R,int rt,int l,int r)
{
    if (L<=l && r<=R){
        //cover[rt]+=(r-l+1);
        d[rt]++;
        flag[rt]+=1;
        return ;
    }
    pushdown(rt,l,r);
    int mid=(l+r)>>1;
    if (L<=mid) inserts(L,R,lson);
    if (R>mid) inserts(L,R,rson);
    up(rt);
}
int main()
{
    while (input()){
    sort(point+1,point+1+n);
    build(1,0,maxn);
    int pre=1;
    int ans=0;
    for (int i=1;i<=n;i++){
        //cout<<i<<endl;
        while (point[pre].x+s<point[i].x){
            remove(point[pre].y,point[pre].y+w,1,0,maxn);
            pre++;
        }
        inserts(point[i].y,point[i].y+w,1,0,maxn);
        ans=max(ans,d[1]);
      }
    printf("%d
",ans);
   }
}

  

原文地址:https://www.cnblogs.com/kkrisen/p/4012315.html