DTOJ3311 寻找

题目

题目描述

“我有个愿望,我希望穿越一切找到你”
这是个二维平面世界,平面上有$n$个特殊的果实,我从$(0,0)$点出发,希望得到尽量多的果实,但是出于某种特殊的原因,我的运动方式只有三种(假设当前我在$(x,y)$):

  1. 我可以走到$(x+1,y)$
  2. 我可以走到$(x,y+1)$
  3. 我可以走到$(x+1,y+1)$

现在我需要你的帮助,帮我找出我最多能够得到多少个果实

输入格式

第一行一个整数$n$表示有多少个被标记的点
接下来$n$行每行两个整数$x,y$表示一个点的坐标

输出格式

一行一个整数表示答案,表示我最多能够得到多少个果实

样例

样例输入

1
2
3
4
5
6
7
8
9
8
-2 -1
-2 -3
0 1
1 1
2 2
3 2
3 2
3 3

样例输出

1
6

数据范围与提示

样例说明

样例输入的点如图所示:
在这里插入图片描述

数据范围

对于$70 \%$的数据$1 \leqslant n \leqslant 10^3$
对于$100 \%$的数据$1 \leqslant n \leqslant 10^5,-10^9 \leqslant x,y \leqslant 10^9$

题解

显然,只有在第一象限、$x$轴和$y$轴的正半轴或者原点上的点可以到达
所以去掉不是第一象限、$x$轴和$y$轴的正半轴或者原点上的点,把剩下的点按照$x$坐标排序,求$y$坐标的最长上升子序列即可
附上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<algorithm>
#include<cstdio>
using namespace std;
struct ppap
{
int x,y;
}a[100010];
int n,len,ans,lcs[100010];
int cmp(const ppap &a,const ppap &b)
{
return a.y<b.y;
}
int main()
{
scanf("%d",&n);
for(int i=1,x,y;i<=n;i++){
scanf("%d%d",&x,&y);
if(x<0||y<0) continue;
a[++len].x=x,a[len].y=y;
}
sort(a+1,a+1+len,cmp);
for(int i=1;i<=len;i++){
if(a[i].x>=lcs[ans]) lcs[++ans]=a[i].x;
else{
int temp=lower_bound(lcs+1,lcs+1+ans,a[i].x)-lcs;
lcs[temp]=a[i].x;
}
}
printf("%d",ans);
}