题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5714
拍照
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行。小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中。
小明位于河的边上,并且可以在河边的任意位置进行拍照,照相机的视野恰好为90度角,只能以垂直于河边的方向进行拍照。河上的船只全都可看作是平行于河边的一条线段,跟河边的距离各不相同,有的正在向左移动,有的正在向右移动,但移动速度恰好都是一样的。小明可以等待恰当的时间让尽量多的船只都走进照相机的视野里,你不需要考虑船只之间会互相遮挡视野的情况。
Input
第一行为T,表示输入数据组数。
下面T组数据,对于每组数据:
第一行是一个数n(1≤n≤104),表示船只的数量。
接下来n行,每行四个整数
x,y,z,d(−106≤x<y≤106,1≤z≤104),表示船只的左端点位置、右端点位置、距离河边的距离,以及航行的方向。d为−1表示向左航行,1表示向右航行。
Output
对第i组数据,输出
Case #i:
然后输出一行,仅包含一个整数,表示最多可以拍到多少完整的船只。
Sample Input
3
2
1 3 1 1
2 4 1 -1
2
1 3 1 -1
2 4 1 1
1
1 4 1 1
Sample Output
Case #1:
2
Case #2:
1
Case #3:
0
题解:对于船[x,y,z],可以在[y-z,x+z]这些位置观测到它,那么就得到了n条线段,由于船速相同,根据运动方向,问题转换为两部分固定线段,一部分左移,一部分右移,求两线段覆盖点的最大值,我们只需要维护下右移线段的左区间最大值,以及左移线段的右区间最大值,那么对于某点i,能观测到的最大值就是左右维护最大值的和。遍历O(n),点排序O(nlog(n));
#include <bits/stdc++.h>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define bug cout<<"bug"<<endl
const int MAXN = 2e5+7;
int N,M,K;
int len1[MAXN],len2[MAXN];
int ans[MAXN];
struct node
{
int a,lef,dir;
}point[MAXN];
int index;
void add_point(int a, int p, int f)
{
point[++index].a=a;
point[index].lef=p;
point[index].dir=f;
}
bool cmp(node x, node y)
{
if(x.a!=y.a)return x.a<y.a;
if(x.lef!=y.lef)return x.lef>y.lef;
return x.dir>y.dir;
}
int main()
{
int T;
scanf("%d",&T);
int cas=0;
while(T--)
{
index=0;
int a,b,x,y,z,p;
scanf("%d",&N);
for(int i=0; i<N; ++i)
{
scanf("%d%d%d%d",&x,&y,&z,&p);
a=y-z,b=x+z;
if(a<=b)
{
add_point(a,1,p);
add_point(b,0,p);
}
}
sort(point+1,point+index+1,cmp);
ans[0]=0;
int temp=0;
for(int i=1; i<=index; ++i)
{
if(point[i].dir==1 && point[i].lef)++temp;
ans[i]=max(ans[i-1],temp);
if(point[i].dir==1 && !point[i].lef)--temp;
}
int f=0,t=0;temp=0;
for(int i=index; i>0; --i)
if(point[i].dir==-1)
{
if(!point[i].lef)++temp;
t=max(t,temp);
f=max(f,ans[i]+t);
if(point[i].lef)--temp;
}
printf("Case #%d:\n%d\n",++cas,f);
}
return 0;
}
/*
3
2
2 3 1 1
0 1 1 -1
2
1 3 1 -1
2 4 1 1
1
1 4 1 1
*/