您的位置:首页 > 其它

GYM 100820 G.Racing Gems(LIS)

2017-07-19 08:58 351 查看
Description

在[0,w]x[0,h]的区域内赛车,初始时可以任意选取x轴上[0,w]内一点作为起点,只要到达y=h在[0,w]范围内任一点即为到达终点,赛车的垂直车速为v,水平车速可以在-v/r~v/r内任意变化,给出该区域内n个钻石的坐标,问在赛车过程中最多可以拿到多少钻石

Input

第一行输入四个整数n,r,w,h,之后n行每行两个整数表示一颗钻石的坐标(1<=n<=1e5,1<=r<=10,1<=w,h<=1e9,0<=x[i]<=w,0<=y[i]<=h)

Output

输出最多可以拿到的钻石数量

Sample Input

5 1 10 10

8 8

5 1

4 6

4 7

7 9

Sample Output

3

Solution

当赛车拿到一个钻石后,其下一个可以拿到的钻石所处范围必须要在以第i个点往上的斜率分别为-r和r的射线之间,设由第i个点发出的两条射线与左右边界交点的纵坐标分别为a[i]和b[i],那么拿到钻石i后可以拿到钻石j等价于钻石j在由第i个点发出的这两条射线之间,进一步等价于a[j]>=a[i],b[j]>=b[i],所以求出每个钻石发出射线与左右两边界的交点(a[i],b[i]),问题变成求这个二维序列的最长上升子序列长度,先按第一维升序排,对第二维求一个最长上升子序列即可

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 1e12
#define maxn 111111
int n,r,w,h;
struct node
{
ll a,b;
bool operator<(const node&c)const
{
if(a!=c.a)return a<c.a;
return b<c.b;
}
}p[maxn];
ll a[maxn],dp[maxn];
int LIS(ll a[])//求序列a的(非严格)最长上升子序列
{
for(int i=1;i<n;i++)dp[i]=INF;
dp[0]=a[0];
int len=1;
for(int i=1;i<n;i++)
{
if(a[i]>=dp[len-1])dp[len++]=a[i];
else dp[upper_bound(dp,dp+n,a[i])-dp]=a[i];
}
return len;
}
int main()
{
while(~scanf("%d%d%d%d",&n,&r,&w,&h))
{
for(int i=0;i<n;i++)
{
ll x,y;
scanf("%I64d%I64d",&x,&y);
p[i].a=1ll*r*x+y,p[i].b=1ll*r*(w-x)+y;
}
sort(p,p+n);
for(int i=0;i<n;i++)a[i]=p[i].b;
printf("%d\n",LIS(a));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: