您的位置:首页 > 编程语言 > Go语言

POI 2001 Goldmine (Treap)

2015-05-14 20:14 267 查看
题目链接

[align=center]Goldmine [/align]

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<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<string.h>
#define nn 110000
#define mod 100003
typedef long long LL;
typedef unsigned long long LLU;
using namespace std;
int s,w;
int n;
pair<int,int>gold[nn];
void Sort(pair<int,int>*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(k<r)
Sort(a,k,r);
}
struct node
{
int val1;
int key;
int val2;
int num;
int sum;
int maxsum;
node* son[2];
}*root;
void update(node *id)
{
id->sum=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,pair<int,int>val)
{
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]->key<id->key)
{
Rotate(id,0);
}
}
else
{
Insert(id->son[1],val);
update(id);
if(id->son[1]->key<id->key)
{
Rotate(id,1);
}
}
}
void Delete(node *&id,pair<int,int>val)
{
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]->key<id->son[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<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<string.h>
#include<vector>
#define nn 310000
#define mod 100003
typedef long long LL;
typedef unsigned long long LLU;
using namespace std;
int s,w;
int n;
pair<int,int>gold[nn];
void Sort(pair<int,int>* 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(k<r)
Sort(a,k,r);
}
int L[nn],R[nn];
int sum[nn],presum[nn];
void build(int id,int l,int r)
{
L[id]=l;
R[id]=r;
sum[id]=presum[id]=0;
if(l==r)
{
return ;
}
int mid=(l+r)/2;
build(2*id,l,mid);
build(2*id+1,mid+1,r);
}
void push_up(int id)
{
sum[id]=sum[2*id]+sum[2*id+1];
presum[id]=max(presum[2*id],sum[2*id]+presum[2*id+1]);
}
void update(int id,int wei,int val)
{
if(L[id]==R[id])
{
sum[id]+=val;
presum[id]+=val;
return ;
}
int mid=(L[id]+R[id])/2;
if(wei<=mid)
{
update(2*id,wei,val);
}
else
update(2*id+1,wei,val);
push_up(id);
}
int ve[nn];
map<int,int>ma;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: