Description
Alice收到一些很特别的生日礼物:区间。即使很无聊,Alice还是能想出关于区间的很多游戏,其中一个是,Alice从中选出最长的不同区间的序列,其中满足每个区间必须在礼物中,另序列中每个区间必须包含下一个区间。
编程计算最长序列的长度。
Input
输入文件第一行包含一个整数N(1<=N<=100000),表示区间的个数。
接下来N行,每行两个整数A和B描述一个区间(1<=A<=B<=1000000)。
Output
输出满足条件的序列的最大长度
思路
第一眼:
这尼玛不是最长不上升子序列么!!!
第二眼:
这尼玛就是最长不上升子序列!!!
本着 刷对傻X题,水过暴力分 竭尽所能的原则,我想都不想就打了O(n²)的原版
打完的一瞬间想到:
不对,这里n忒大,会爆!
于是就用复杂度为O(nlogn)的最长不上升子序列算法
开始之前对坐标排序,保证x从小到大且当x相等时y从大到小,实现可用多关键字的快排
考试的时候想不到,也算是一种水平低の体现吧
Code
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
struct line
{
int start,end;
};
line v[100001];
long long t[100001],f[100001];
bool cmp(line x,line y)
{
return (x.start<y.start)||((x.start==y.start)&&(x.end>y.end));
}
int max(int x,int y)
{
return x>y?x:y;
}
int find(int i,int j,int x)
{
while (i<=j)
{
int mid=i+(j-i)/2;
i=t[mid]>=x?mid+1:i;
j=t[mid]<x?mid-1:j;
}
return i;
}
int main()
{
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d%d",&v[i].start,&v[i].end);
memset(t,0xffffffff,sizeof(t));
sort(v+1,v+n+1,cmp);
long long ans=0;
for (int i=1;i<=n;i++)
{
int j=find(1,i,v[i].end);
f[i]=j;
t[f[i]]=max(v[i].end,t[f[i]]);
ans=max(f[i],ans);
}
printf("%lld\n",ans);
return 0;
}
int main()
{
int n;
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d%d",&v[i].start,&v[i].end);
memset(t,0xffffffff,sizeof(t));
sort(v+1,v+n+1,cmp);
long long ans=0;
for (int i=1;i<=n;i++)
{
int j=find(1,i,v[i].end);
f[i]=j;
t[f[i]]=v[i].end>t[f[i]]?v[i].end:t[f[i]];
ans=f[i]>ans?f[i]:ans;
}
printf("%lld\n",ans);
return 0;
}
var
n:longint;
x,y,f,t:array[0..100000]of int64;
procedure swap(var i,j:int64);
var
tmp:longint;
begin
tmp:=i;
i:=j;
j:=tmp;
end;
function min(x,y:int64):int64;
begin
min:=x;
if y<x then
min:=y;
end;
procedure qsort(l,r:int64);
var
i,j,key,ley:longint;
begin
if l>=r then exit;
i:=l;
j:=r;
key:=x[l+random(r-l+1)];
ley:=y[l+random(r-l+1)];
repeat
while (x[i]<key)or(x[i]=key)and(y[i]>ley) do inc(i);
while (x[j]>key)or(x[j]=key)and(y[j]<ley) do dec(j);
if i<=j then
begin
swap(x[i],x[j]);
swap(y[i],y[j]);
inc(i);
dec(j);
end;
until i>j;
qsort(l,j);
qsort(i,r);
end;
function find(i,j,v:int64):int64;
var
mid:longint;
begin
while i<=j do
begin
mid:=i+(j-i)div 2;
if t[mid]>=v then
i:=mid+1
else
j:=mid-1;
end;
find:=i;
end;
procedure main;
var
i,j,max,ans:longint;
begin
for i:=1 to n do t[i]:=-maxlongint;
qsort(1,n);
ans:=0;
i:=0;
for i:=1 to n do
begin
j:=find(1,i,y[i]);
f[i]:=j;
if y[i]>t[f[i]] then
t[f[i]]:=y[i];
if f[i]>ans then
ans:=f[i];
end;
writeln(ans);
end;
procedure init;
var
i:longint;
begin
randomize;
readln(n);
for i:=1 to n do
readln(x[i],y[i]);
end;
begin
init;
main;
end.