UVALive - 7374 Racing Gems 二维非递减子序列

题目链接:

http://acm.hust.edu.cn/vjudge/problem/356795

Racing Gems

Time Limit: 3000MS
#### 问题描述 > You are playing a racing game. Your character starts at the > x axis (y = 0) and proceeds up the race track, which has a > boundary at the line x = 0 and another at x = w. You may > start the race at any horizontal position you want, as long as > it is within the track boundary. The finish line is at y = h, > and the game ends when you reach that line. You proceed at > a fixed vertical velocity v, but you can control your horizontal > velocity to be any value between −v/r and v/r, and change it at any time. > There are n gems at specific points on the race track. Your job is to collect as many gems as > possible. How many gems can you collect?

输入

The input file contains several test cases, each of them as described below.
The first line of input contains four space-separated integers n, r, w, and h (1 ≤ n ≤ 105
, 1 ≤ r ≤ 10,
1 ≤ w, h ≤ 109
). Each of the following n lines contains two space-separated integers xi and yi
, denoting
the coordinate of the i-th gem (0 ≤ xi ≤ w, 0 < yi ≤ h). There will be at most one gem per location.
The input does not include a value for v.

输出

For each case, print, on a single line, the maximum number of gems that can be collected during the
race.

样例

sample input
5 1 10 10
8 8
5 1
4 6
4 7
7 9
5 1 100 100
27 75
79 77
40 93
62 41
52 45
10 3 30 30
14 9
2 20
3 23
15 19
13 5
17 24
6 16
21 5
14 10
3 6

sample output
3
3
4

题意

以辆赛车可以从x轴上任意点出发,他的水平速度允许他向每向上移动1个单位,就能向左或向右移动1/r个单位(也就是它的辐射范围是个等腰三角形)
现在赛车从x轴出发,问它在到达终点前能吃到的最多钻石。

题解

考虑每个钻石的向下辐射范围,并且将其投影到x轴上的两个点,(辐射范围与x轴的两个焦点),然后我们就把题目转化成了一个区间覆盖问题,我们用x<y表示x区间被y区间覆盖,即求二维最长的上升子序列:a1<=a2<=...<=an。
我们按每个钻石的左端点排序,然后跑右端点的最长不下降子序列就可以了。由于数据比较大,用二分处理成nlogn的复杂度。

代码

#include<map>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<string>
#define X first
#define Y second
#include<iostream>
#include<algorithm>
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define M (l+(r-l)/2)
#define bug(a) cout<<#a<<" = "<<a<<endl
using namespace std;

typedef __int64 LL;

const int maxn=1e5+10;

struct Node{
	LL a,b;
	bool operator <(const Node& tmp) const {
		return a>tmp.a||a==tmp.a&&b<tmp.b;
	}
}nds[maxn];

int n,w,h;
LL r;

LL ra[maxn];
int dp[maxn];

int main() {
	memset(dp,0,sizeof(dp));
	scanf("%d%I64d%d%d",&n,&r,&w,&h);
	for(int i=1;i<=n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		//映射到x轴的左端点 
		nds[i].a=r*x-y;
		//映射到x轴的右端点 
		nds[i].b=r*x+y;
	}
	//按左端点降序排,左端点相同时右端点升序排 
	sort(nds+1,nds+n+1);
	//初始的ra数组为空 
	int tot=1,ans=1; 
	for(int i=1;i<=n;i++){
		//二分查找 
		int pos=upper_bound(ra+1,ra+tot,nds[i].b)-ra;
		dp[i]=pos;
		ra[pos]=nds[i].b;
		if(tot==pos) tot++;
		ans=max(ans,dp[i]);
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2016-08-06 00:10  fenicnn  阅读(343)  评论(0编辑  收藏  举报