POI 2001 Goldmine(Treap)
テーマリンク
Goldmine
Time Limit:1000 MSMemory Limit:30000 KB Total Submit:157 Acctepted:50
Description Byteman,one of the most derving employee of The Goldmine of Byteland,about to retire by the end of the year.The Goldmine management would liketo reward hihihimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimition 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 ara of the loam(ia nugget lies the border of the lot、then it is is the the the of the lot).Youtasssssssssssssssssk proproproprograaaaatototototototototototototototototototototototototototototototototototototoloam( iffffffm thethethethethethethethethethethethethethethethethethethethethethethethethetheアニメーションIn order to simplify we asume that the terran of the Goldmine is boundless、but the ara of goldnugggetsoccurrence is limited.Task Write a program which:1.reads the location of gonugggts、2.ppputtitititiaaaaaaaaaaaaaaaaaaaaaaaaaaaaathethethethethethegogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogowrites the result.
Input In the first line there are two positive integers 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 respively.The is one positive integer n written in the second line,(1<=n==15,000)It denotes the number of nuggets in the ara of the Goldmine.In the follwing n ininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininin
Output The out shout contain exactly one integer equal to the value of the most valuable lot of a given size.
Sample Input 1 2 12 0 1 2 3 3 5 5 5 4 4 1 4 0 5 5 0 2 3 3 2 2 2 2
Sample Output 4
ソurce
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樹状配列で解決できます.
ツリーコードのバランス:
Goldmine
Time Limit:1000 MSMemory Limit:30000 KB Total Submit:157 Acctepted:50
Description Byteman,one of the most derving employee of The Goldmine of Byteland,about to retire by the end of the year.The Goldmine management would liketo reward hihihimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimimition 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 ara of the loam(ia nugget lies the border of the lot、then it is is the the the of the lot).Youtasssssssssssssssssk proproproprograaaaatototototototototototototototototototototototototototototototototototototoloam( iffffffm thethethethethethethethethethethethethethethethethethethethethethethethethetheアニメーションIn order to simplify we asume that the terran of the Goldmine is boundless、but the ara of goldnugggetsoccurrence is limited.Task Write a program which:1.reads the location of gonugggts、2.ppputtitititiaaaaaaaaaaaaaaaaaaaaaaaaaaaaathethethethethethegogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogogowrites the result.
Input In the first line there are two positive integers 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 respively.The is one positive integer n written in the second line,(1<=n==15,000)It denotes the number of nuggets in the ara of the Goldmine.In the follwing n ininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininin
Output The out shout contain exactly one integer equal to the value of the most valuable lot of a given size.
Sample Input 1 2 12 0 1 2 3 3 5 5 5 4 4 1 4 0 5 5 0 2 3 3 2 2 2 2
Sample Output 4
ソurce
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
",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
",ans);
}
return 0;
}