您的位置:首页 > 其它

NOIP模拟赛 寻找

2016-11-15 11:05 225 查看
题目描述

“我有个愿望,我希望穿越一切找到你。”

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

1、我可以走到(x+1,y)

2、我可以走到(x,y+1)

3、我可以走到(x+1,y+1)

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

输入

第一行一个整数n表示有多少个被标记的点

接下来n行每行两个整数x,y表示一个点的坐标

输出

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

样例输入

8
-2 -1
-2 -3
0 1
1 1
2 2
3 2
3 2
3 3


样例输出

6


数据范围

对于70%的数据1<=n<=1000

对于100%的数据1<=n<=100000,-10^9<=x,y<=10^9

题解:

由于只能从(0,0)向下向右向右下走,所以只有第一象限内的点有用。将每个点按x为第一关键字,y为第二关键字排序。

求排序后的序列的最长不下降子序列即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
inline int F(){
int x=0,c=getchar(),f=1;
for(;c<48||c>57;c=getchar())
if(!(c^45))
f=-1;
for(;c>47&&c<58;c=getchar())
x=(x<<1)+(x<<3)+c-48;
return x*f;
}
struct point{
int x,y;
bool operator<(const point h)const{
if(x^h.x)
return x<h.x;
return y<h.y;
}
}p
;
int n,ind,stk
;
int main(){
freopen("find.in","r",stdin),
freopen("find.out","w",stdout);
n=F();
for(int i=1;i<=n;i++){
p[i].x=F(),
p[i].y=F();
if(p[i].x>=0&&p[i].y>=0)
p[++ind].x=p[i].x,
p[ind].y=p[i].y;
}
sort(p+1,p+1+ind);
stk[++stk[0]]=p[1].y;
for(int i=2;i<=ind;i++)
if(p[i].y>=stk[stk[0]])
stk[++stk[0]]=p[i].y;
else{
int l=1,r=stk[0],w=0;
while(l<=r){
int mid=l+r>>1;
if(stk[mid]<=p[i].y)
l=mid+1;
else
w=mid,
r=mid-1;
}
stk[w]=p[i].y;
}
printf("%d\n",stk[0]);
fclose(stdin),
fclose(stdout);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: