首页 > 代码库 > [POI 2001+2014acm上海邀请赛]Gold Mine/Beam Cannon 线段树+扫描线

[POI 2001+2014acm上海邀请赛]Gold Mine/Beam Cannon 线段树+扫描线

Description 

Byteman, one of the most deserving employee of The Goldmine of Byteland, is about to retire by the end of the year. The Goldmine management would like to reward him in acknowledgment of his conscientious work. As a reward Byteman may receive a small lot - a rectangular piece of the mine‘s area with sides of length s and w parallel to the axes of the coordinate system. He may choose the location of the lot. Of course, a value of the lot depends on the location. The value of the lot is a number of gold nuggets in the area of the lot (if a nugget lies on the border of the lot, then it is in the area of the lot). Your task is to write a program which computes the maximal possible value of the lot (the value of the lot with the best location). In order to simplify we assume that the terrain of the Goldmine is boundless, but the area of gold nuggets occurrence is limited. 

Task
Write a program which:

1.reads the location of gold nuggets, 
2.computes the maximal value of a lot (i.e. the maximal number of gold nuggets on the lot of given size), 
3.writes the result . 
Input 

In the first line there are two positive integers s and w separated by a single space, (1<=s,w<=10 000); they denote the lengths of lot‘s sides - parallel to the OX-axe and OY-axe respectively. There is one positive integer n written in the second line, (1<=n<=15 000). It denotes the number of nuggets in the area of the Goldmine. In the following n lines there are written the coordinates of the nuggets. Each of these lines consists of two integers x and y, (-30 000<=x,y<=30 000), separated by a single space and denoting the x and the y coordinate of a nugget respectively.

Output 

The out should contain exactly one integer equal to the value of the most valuable lot of a given size.

Sample Input 

1 2
12
0 0
1 1
2 2
3 3
4 5
5 5
4 2
1 4
0 5
5 0
2 3
3 2

Sample Output 

4



题目大意

给定二维平面上的N个点,寻找一个w*s(高w宽s,被这个点坑好久)的矩形,使得当中包括最多的点。

上海邀请赛B题的题意和这一题类似。



思路

黑书原题。

将每个点看作是两个事件从左到右进行扫描(能够维护队列控制队头和队尾的差不超过宽度,也能够依照时间顺序排序后进行处理),每个点抽象成长度为矩形高度的线段,线段经过次数最多的点便是结果。

这样就把O(n^2)降维至O(n*log(A)),A为点纵坐标的范围。

在这里能够提交

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

ps:太弱了,不仅当场没出这道题并且后来做的时候还W一天,基础还是有待夯实啊。
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <vector>
#include <cstring>
using namespace std;
struct node{
    int t,pos,st;
}ha[200000];
int x1,x2,v;
int _max;
int n,w,h;
int cmp(node x,node y)
{
    return (x.t<y.t);//依照时间先后顺序排序,先删除点再加入点
}
int maxv[400000],addv[400000];
void maintain(int o,int L,int R)
{
    int lc=o<<1;
    int rc=lc+1;
    maxv[o]=0;
    if (R>L)
    {
        maxv[o]=max(maxv[lc],maxv[rc]);
    }
    maxv[o]+=addv[o];
}
void update(int o,int L,int R)
{
    int lc=o<<1;
    int rc=lc+1;
    if (x1<=L&&x2>=R) addv[o]+=v;
    else {
        int M=L+(R-L)/2;
        if (x1<=M) update(lc,L,M);
        if (x2>M) update(rc,M+1,R);
    }
    maintain(o,L,R);
}
void query(int o,int L,int R,int add)
{
    int lc=o<<1;
    int rc=lc+1;
    if (x1<=L&&x2>=R) _max=max(_max,maxv[o]+add);
    else {
        int M=L+(R-L)/2;
        if (x1<=M) query(lc,L,M,addv[o]+add);
        if (x2>M) query(rc,M+1,R,addv[o]+add);
    }
}
int main()
{
    while(~scanf("%d%d%d",&w,&h,&n))
    {
        memset(maxv,0,sizeof(maxv));
        memset(addv,0,sizeof(addv));
        _max=0;
        int o,p,pt=0;
        memset(ha,0,sizeof(ha));
        for (int i=1;i<=n;i++)
            {
                scanf("%d%d",&o,&p);
                ha[++pt].t=o;
                ha[pt].pos=p+30001;
                ha[pt].st=1;
                ha[++pt].t=o+w+1;
                ha[pt].pos=p+30001;
                ha[pt].st=-1;
            }
        sort(ha+1,ha+pt+1,cmp);//将全部时间点排序
        for (int i=1;i<=pt;i++)
        {
            x1=ha[i].pos;
            x2=ha[i].pos+h;
            x2=min(x2,60001);
            v=ha[i].st;
            update(1,1,60001);//更新点数
            if (ha[i].t!=ha[i+1].t||i==pt)//直至同一时间点的全部更新完毕之后才输出
                {
                 x1=1;
                 x2=60001;
                 query(1,1,60001,0);
                }
        }
        printf("%d\n",_max);
    }
}



[POI 2001+2014acm上海邀请赛]Gold Mine/Beam Cannon 线段树+扫描线