导弹拦截数据加强版
nlogn的最长上升/不上升子序列
先设一个数组low
把第一个数放进去
此时len=1
后面的数如果大于low[len]
len++
放到新的low[len]
如果小于等于low[len]
在前面找一个大于它的最小的数
顺便这里安利一下lower_bound()
用这个数来替换前面的数
二分太恶心了
不想找边界
lower_bound()是个好东西
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<climits>
#include<string>
#include<cstdlib>
#include<map>
#include<ctime>
#define MAX 1000000007
#define LL long long
using namespace std;
int n,i,j,a[300005],h[300005],tot,ans1,ans2,low[300005],len,pos,up[300005];
int part(int l,int r,int lend)
{
while(l<=r)
{
int mid=(l+r)/2;
if(up[mid]>=a[lend])
{
l=mid+1;
}
else
{
r=mid-1;
}
}
return l;
}
int main()
{
n=1;
while(scanf("%d",&a[n])!=EOF)
{
n++;
}
n--;
/////////////////////////////////////////////////////////////
up[1]=a[1];
len=1;
for(i=2;i<=n;i++)
{
if(a[i]<=up[len])
{
len++;
up[len]=a[i];
}
else
{
pos=part(1,len,i);
up[pos]=a[i];
}
}
ans1=len;
//////////////////////////////////////////////////////////////
low[1]=a[1];
len=1;
for(i=2;i<=n;i++)
{
if(a[i]>low[len])
{
len++;
low[len]=a[i];
}
else
{
pos=lower_bound(low,low+len+1,a[i])-low;
low[pos]=a[i];
}
}
ans2=len;
////////////////////////////////////////////////////////////////////
printf("%d\n%d",ans1,ans2);
return 0;
}