小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行。小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中。
小明位于河的边上,并且可以在河边的任意位置进行拍照,照相机的视野恰好为90度角,只能以垂直于河边的方向进行拍照。河上的船只全都可看作是平行于河边的一条线段,跟河边的距离各不相同,有的正在向左移动,有的正在向右移动,但移动速度恰好都是一样的。小明可以等待恰当的时间让尽量多的船只都走进照相机的视野里,你不需要考虑船只之间会互相遮挡视野的情况。
input
第一行为T,表示输入数据组数。
下面T组数据,对于每组数据:
第一行是一个数n,表示船只的数量。
接下来n行,每行四个整数 x,y,z,d,表示船只的左端点位置、右端点位置、距离河边的距离,以及航行的方向。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
hint
1<=n<=10000−106<=x<y<=1061<=z<=10000
很不错的思维题。网上的题解我觉得这个写得最详细:
传送门
其实就是两个前缀和+线形扫描的事情。前缀和的方法就是[左端点]+1,[右端点+1]-1,然后都加起来,就变成了当前这个点的值。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=2020005;
int t,n,x,y,z,v,ans;
int s[N],p[N],a[N],b[N];
int main()
{
cin>>t;
for(int w=1;w<=t;w++)
{
cin>>n;
ans=0;
for(int i=1;i<=N;i++)
{
a[i]=0;
b[i]=0;
}
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&x,&y,&z,&v);
if(y-x<=2*z)
{
int l=y-z,r=x+z;
l=l+1e6+1e4+1;
r=r+1e6+1e4+1;
if(v==-1)
{
a[l]++;
a[r+1]--;
}
else
{
b[l]++;
b[r+1]--;
}
}
}
for(int i=1;i<=N;i++)
{
s[i]=s[i-1]+a[i];
p[i]=p[i-1]+b[i];
}
int Right=0;
for(int i=1;i<=N;i++)
{
Right=max(Right,p[i]);
ans=max(ans,s[i]+Right);
}
printf("Case #%d:\n",w);
printf("%d\n",ans);
}
return 0;
}