题目
奶牛排队 sort
时间限制:1.0s
内存限制:256MB
问题描述
约翰日常折腾奶牛系列。。。这一次约翰要选出尽可能多的奶牛排成一队。
然而约翰非常的挑剔,他要求奶牛排成的队必须身高和体重都是上升的序列。
问最多可以挑多少头奶牛排成一队?
输入格式
第一行一个正整数n
第二行共有n个数字,分别是奶牛的身高h1,h2……hn。
第三行共有n个数字,分别是奶牛的体重w1,w2……wn。
输出格式
只有一行,为最多的奶牛数量。
样例输入
5
5 7 3 6 8
3 6 7 8 2
样例输出
2
提示
挑出奶牛后是可以重新给他们排队的
评测用例规模与约定
对于40%的数据,1 <= n <= 1000
对于100%的数据,1 <= n <= 100000
对于100%的数据,1 <= hi,wi <= 2147483647
分析
- 双关键字排序 ( h相同时w从大到小排 )
- 十万数据量– O( nlogn ) 最长上升子序列( LIS ):栈+二分
O( nlogn ) 最长上升子序列( LIS ):栈+二分算法详解(by RyanWang)***
开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。 最长序列长度即为栈的大小top。
这也是很好理解的,对于x和y,如果x < y且Stack[y] < Stack[x],用Stack[x]替换Stack[y],此时的最长序列长度没有改变但序列Q的”潜力”增大了。
举例:原序列为1,5,8,3,6,7
栈为1,5,8,此时读到3,用3替换5,得到1,3,8; 再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。
代码
#include<bits/stdc++.h>
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define N 1000001
#define M 10001
#define LL long long
#define oo 0x7fffffff
using namespace std;
int read()
{
int f=1,s=0;
char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return f*s;
}
int m,n,k;
int tot,cnt,ans,top;
int stk[N];
struct node{
int h,w;
}a[N];
bool my_cmp( const node &a , const node &b ) //排序( h相同w从大到小 )
{
if( a.h < b.h ) return true;
if( a.h==b.h && a.w>b.w ) return true;
return false;
}
void LIS_ex() // O(nlogn)最长上升子序列
{
F(i,1,n)
{
if( a[i].w > stk[top] ) stk[++top]=a[i].w; //now大于栈顶即入栈
else
{
int l,r,mid;
l=1;
r=top;
while(l<=r) //二分查找第一个大于now 的元素并替换
{
mid=( l+r )>>1;
if( a[i].w>stk[mid] ) l=mid+1;
else r=mid-1;
}
stk[l]=a[i].w;
}
}
}
int main()
{
freopen( "sort.in" ,"r" ,stdin );
freopen( "sort.out","w" ,stdout );
n=read();
F(i,1,n)
{
a[i].h=read();
}
F(i,1,n)
{
a[i].w=read();
}
sort( a+1 ,a+n+1 ,my_cmp );
LIS_ex();
cout<< top <<endl;
return 0;
}
测试结果