小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行。小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中。
小明位于河的边上,并且可以在河边的任意位置进行拍照,照相机的视野恰好为90度角,只能以垂直于河边的方向进行拍照。河上的船只全都可看作是平行于河边的一条线段,跟河边的距离各不相同,有的正在向左移动,有的正在向右移动,但移动速度恰好都是一样的。小明可以等待恰当的时间让尽量多的船只都走进照相机的视野里,你不需要考虑船只之间会互相遮挡视野的情况。
思路:
首先得发现这两条规律:
1.设船到河岸的距离为h,则如果 y-x > 2*h ,则这条船不可能被完整拍到。
2.设河岸[l,r]范围内能够拍到船,则 l=y-h , r =x+h 。
然后计算每个河岸上的点能够拍到多少条船,两个方向分别处理。
后面的真是不好叙述,如果当面用草稿纸说明会比较方便,看代码吧。数据范围太大,需要离散化。
#include "algorithm"
#include "iostream"
#include "cstring"
#include "cstdio"
#include "string"
#include "stack"
#include "cmath"
#include "queue"
#include "set"
#include "map"
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
const int mod = 1e9 +7;
//从右开始顺时针
int dir4[4][2]= {0,1,1,0,0,-1,-1,0};
int dir8[8][2]= {0,1,1,1,1,0,1,-1,0,-1,-1,-1,-1,0,-1,1};
int n;
int lisan[maxn<<1];
int lsum[maxn<<1];
int rsum[maxn<<1];
struct Ship
{
int x,y,h,d;
int l,r;
bool see()
{
return (y-x) <= (h<<1) ;
}
} ship[10000+5];
int main()
{
//freopen("in_3.txt","r",stdin);
int t;
scanf("%d",&t);
for(int ii=1; ii<=t; ii++)
{
printf("Case #%d:\n",ii);
memset(lsum,0,sizeof lsum);
memset(rsum,0,sizeof rsum);
scanf("%d",&n);
int index = 0;
for(int i=0; i<n; i++)
{
scanf("%d%d%d%d",&ship[i].x,&ship[i].y,&ship[i].h,&ship[i].d);
if( !ship[i].see() )
{
//printf("cant see:%d\n",i);
continue;
}
ship[i].l = ship[i].y-ship[i].h;
ship[i].r = ship[i].x+ship[i].h;
lisan[index++] = ship[i].l;
lisan[index++] = ship[i].r;
}
sort(lisan,lisan+index);
int mm=1;
for(int i=1;i<index;++i)
{
if( lisan[i]!=lisan[i-1] )
{
lisan[mm++]=lisan[i];
}
}
for(int i=0;i<n;++i)
{
if( !ship[i].see() )
{
//printf("cant see:%d\n",i);
continue;
}
int l = lower_bound(lisan,lisan+mm,ship[i].l) - lisan;
int r = lower_bound(lisan,lisan+mm,ship[i].r) - lisan;
if( ship[i].d==1 ) //right
{
rsum[l] ++;
rsum[r+1]--;
}
else
{
lsum[l] ++;
lsum[r+1]--;
}
}
for(int i=1 ;i<mm;++i)
{
rsum[i] +=rsum[i-1];
lsum[i] +=lsum[i-1];
}
int rm = 0,ans=0;
for(int i=0;i<mm;++i)
{
rm = max(rm,rsum[i]);
ans = max(ans,rm+lsum[i]);
}
printf("%d\n",ans);
}
return 0;
}