POI 2001 Goldmine (Treap)

题目链接

Goldmine

Time Limit:1000MSMemory Limit:30000KB
Total Submit:157Accepted:50

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

Source

POI 2001 III Stage

题意:二维平面上有n个整数点,现在有一个长方形长为S,宽为W。长和宽分别与X轴、Y轴平行。问这个矩形最多能覆盖多少个点?(点在长方形的边上也算覆盖)

题解:先将点按X排序,从前到后把点扫一遍,每次把当前点加入集合,维护集合,是集合中点到当前点的距离不超过S。对于当前集合来说,我们要求解一个Y轴方向的长度为w的区间最多能覆盖集合中的多少个点?

对于这个问题,设有一个点的纵坐标为y,我们在数组下标y处+1,在数组下标(y+w+1)处-1。那么数组的前缀和sum[i]就是区间[i-w,i]中点的个数。那么问题就是求该数组的最大前缀和。

这个问题可以用平衡树or线段树or树状数组解决。

平衡树代码:

#include
#include
#include
#include
#include
#define nn 110000
#define mod 100003
typedef long long LL;
typedef unsigned long long LLU;
using namespace std;
int s,w;
int n;
pairgold[nn];
void Sort(pair*a,int l,int r)
{
    if(r==l)
        return ;
    int tem=rand()%(r-l+1)+l;
    swap(*(a+tem),*(a+r));
    int i;
    int k=l;
    for(i=l;i<=r;i++)
    {
        if(*(a+i)<=*(a+r))
        {
            swap(*(a+k),*(a+i));
            k++;
        }
    }
    if(k-2>l)
        Sort(a,l,k-2);
    if(ksum=id->val2;
    if(id->son[0]!=NULL)
    {
        id->sum+=id->son[0]->sum;
        id->maxsum=max(id->son[0]->maxsum,id->son[0]->sum+id->val2);
    }
    else
        id->maxsum=id->val2;
    if(id->son[1]!=NULL)
    {
        id->sum+=id->son[1]->sum;
        if(id->son[0]!=NULL)
            id->maxsum=max(id->maxsum,id->son[0]->sum+id->val2+id->son[1]->maxsum);
        else
            id->maxsum=max(id->maxsum,id->val2+id->son[1]->maxsum);
    }
}
void Rotate(node* &id,int d)
{
    node* tem=id->son[d];
    id->son[d]=tem->son[d^1];
    tem->son[d^1]=id;
    update(id);
    update(tem);
    id=tem;
}
void Insert(node* &id,pairval)
{
    if(id==NULL)
    {
        id=new node;
        id->num=1;
        id->val1=val.first;
        id->val2=val.second;
        id->key=(rand()*rand())%nn;
        id->sum=val.second;
        id->maxsum=val.second;
        id->son[0]=id->son[1]=NULL;
        return ;
    }
    if(id->val1==val.first)
    {
        id->num++;
        id->val2+=val.second;
        update(id);
    }
    else if(id->val1>val.first)
    {
        Insert(id->son[0],val);
        update(id);
        if(id->son[0]->keykey)
        {
            Rotate(id,0);
        }
    }
    else
    {
        Insert(id->son[1],val);
        update(id);
        if(id->son[1]->keykey)
        {
            Rotate(id,1);
        }
    }
}
void Delete(node *&id,pairval)
{
    if(id==NULL)
        return ;
    if(id->val1==val.first)
    {
        if(id->num==1)
        {
            if(id->son[0]==NULL)
                id=id->son[1];
            else if(id->son[1]==NULL)
                id=id->son[0];
            else
            {
                if(id->son[0]->keyson[1]->key)
                {
                    Rotate(id,0);
                    Delete(id->son[1],val);
                }
                else
                {
                    Rotate(id,1);
                    Delete(id->son[0],val);
                }
            }
        }
        else
        {
            id->num--;
            id->val2-=val.second;
        }
    }
    else if(id->val1>val.first)
    {
        Delete(id->son[0],val);
    }
    else
    {
        Delete(id->son[1],val);
    }
    if(id!=NULL)
        update(id);
}
int main()
{
    int i;
    while(scanf("%d%d",&s,&w)!=EOF)
    {
        root=NULL;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&gold[i].first,&gold[i].second);
        }
        Sort(gold,1,n);
        int pre=1;
        int ans=0;
        for(i=1;i<=n;i++)
        {
            while(gold[i].first-gold[pre].first>s)
            {
                Delete(root,make_pair(gold[pre].second,1));
                Delete(root,make_pair(gold[pre].second+w+1,-1));
                pre++;
            }
            Insert(root,make_pair(gold[i].second,1));
            Insert(root,make_pair(gold[i].second+w+1,-1));
            ans=max(ans,root->maxsum);
        }
        printf("%d\n",ans);
    }
    return 0;
}

线段树代码:

#include
#include
#include
#include
#include
#include
#define nn 310000
#define mod 100003
typedef long long LL;
typedef unsigned long long LLU;
using namespace std;
int s,w;
int n;
pairgold[nn];
void Sort(pair* a,int l,int r)
{
    if(l==r)
        return ;
    int tem=(rand()*rand())%(r-l+1)+l;
    swap(*(a+tem),*(a+r));
    int k=l;
    for(int i=l;i<=r;i++)
    {
        if(*(a+i)<=*(a+r))
        {
            swap(*(a+i),*(a+k));
            k++;
        }
    }
    if(k-2>l)
        Sort(a,l,k-2);
    if(kma;
int main()
{
    int i;
    while(scanf("%d%d",&s,&w)!=EOF)
    {
        scanf("%d",&n);
        int lv=0;
        ma.clear();
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&gold[i].first,&gold[i].second);
            ve[++lv]=gold[i].second;
            ve[++lv]=gold[i].second+w+1;
        }
        sort(ve+1,ve+lv+1);
        lv=unique(ve+1,ve+lv+1)-ve-1;
        for(i=1;i<=lv;i++)
        {
            ma[ve[i]]=i;
        }
        Sort(gold,1,n);
        int pre=1;
        build(1,1,lv);
        int ans=0;
        for(i=1;i<=n;i++)
        {
            while(gold[i].first-gold[pre].first>s)
            {
                update(1,ma[gold[pre].second],-1);
                update(1,ma[gold[pre].second+w+1],1);
                pre++;
            }
            update(1,ma[gold[i].second],1);
            update(1,ma[gold[i].second+w+1],-1);
            ans=max(ans,presum[1]);
        }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(数据结构)