您的位置:首页 > 其它

【NOIP2016提高A组集训第5场11.2】寻找

2016-11-07 22:09 387 查看
Description

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

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

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

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

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

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

Input

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

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

Output

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

Sample Input

8

-2 -1

-2 -3

0 1

1 1

2 2

3 2

3 2

3 3

Sample Output

6

Data Constraint

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

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

题解

二维偏序or最长不下降子序列

贴代码

var
tree:array[0..500005]of longint;
a:array[0..100005,1..2]of longint;
c:array[0..100005]of longint;
i,j,k,l,n,x,y,tot,ans,last:longint;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
procedure qsort(l,r,x:longint);
var
i,j,mid,mid1,y:longint;
begin
i:=l;
j:=r;
mid:=a[(i+j) div 2,x];
if x=1 then y:=2 else y:=1;
mid1:=a[(i+j) div 2,y];
repeat
while (a[i,x]<mid) or ((a[i,x]=mid) and (a[i,y]<mid1)) do inc(i);
while (a[j,x]>mid) or ((a[j,x]=mid) and (a[j,y]>mid1)) do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
inc(i);
dec(j);
end;
until i>j;
if i<r then qsort(i,r,x);
if l<j then qsort(l,j,x);
end;
procedure find(v,l,r,x,y:longint);
var
mid:longint;
begin
if (l=x) and (r=y) then tot:=max(tot,tree[v]) else
begin
mid:=(l+r) div 2;
if y<=mid then find(v*2,l,mid,x,y) else
if x>mid then find(v*2+1,mid+1,r,x,y) else
begin
find(v*2,l,mid,x,mid);
find(v*2+1,mid+1,r,mid+1,y);
end;
end;
end;
procedure change(v,l,r,x:longint);
var
mid:longint;
begin
tree[v]:=max(tree[v],tot);
if l=r then exit;
mid:=(l+r) div 2;
if x<=mid then change(v*2,l,mid,x) else change(v*2+1,mid+1,r,x);
end;
begin
assign(input,'find.in'); reset(input);
assign(output,'find.out'); rewrite(output);
readln(n);
for i:=1 to n do
begin
readln(x,y);
if (x>=0) and (y>=0) then
begin
inc(l);
a[l,1]:=x; a[l,2]:=y;
end;
end;
n:=l;
qsort(1,n,2);
a[0,2]:=-1;
for i:=1 to n do
if a[i,2]=a[i-1,2] then c[i]:=c[i-1] else c[i]:=c[i-1]+1;
for i:=1 to n do a[i,2]:=c[i];
last:=c
;
qsort(1,n,1);
for i:=n downto 1 do
begin
tot:=0;
find(1,1,last,a[i,2],last);
inc(tot);
if tot>ans then ans:=tot;
change(1,1,last,a[i,2]);
end;
writeln(ans);
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: