NOIP1999 提高组-导弹拦截
题目

题目思路
分别求一个最大不下降子序列和最大上升子序列
为什么第二问是最大不上升子序列是因为 :
103 99 83 102 70 89 70 99 71
一个系统能解决83 就不能解决89 99
同理能解决89 就不能83 因为这个是有顺序的
所以是3个
然后在写的过程中
if(c1[mid]>=x)r=mid-1;
else if(c1[mid]==x)break;
是>=,我当时一直想这跟那个模板lcs又不同 肯定会有重复数字的 那怎么办 后面想是不是cmid=x就直接结束 其实这样不可以的
比如
1 2 8 9 15 x=8
进来判断完直接退出 返回l=1这是不行的
所以r=mid-1是必须的 然后最终返回L=3
然后就是数据范围了 他没给好 wa16以后其实但是1e5的数据 题面却说1e4
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<math.h>
using namespace std;
int n;
int step;
int a[500005];
int len=1;
int c[500005];
int c1[500005];
int len1=1;
int find1(int x)
{
int mid;
int l=1;int r=len1;
while(l<=r)
{
mid=(l+r)>>1;
if(c1[mid]>=x)r=mid-1;
// else if(c1[mid]==x)break;
else{
l=mid+1;
}
}
return l;
}
//----------------------------
//---------------------------
//----------------------------
int find(int x)
{
int mid;
int l=1;int r=len;
while(l<=r)
{
mid=(l+r)>>1;
if(c[mid]<x)r=mid-1;
else{
l=mid+1;
}
}
return l;
}
int main()
{
while(scanf("%d",&n)!=EOF)a[++step]=n;
c[1]=a[1];
for(int i=2;i<=step;i++)
{
if(a[i]<=c[len])
{
c[++len]=a[i];
}
else
{
int j=find(a[i]);
c[j]=a[i];
}
}
cout<<len<<endl;
//-----------------------------
//------------------------------
//------------------------------
//---------------------------
c1[1]=a[1];
for(int i=2;i<=step;i++)
{
if(a[i]>c1[len1])
{
c1[++len1]=a[i];
}
else
{
int j=find1(a[i]);
c1[j]=a[i];
//cout<<c[j]<<endl;
}
}
cout<<len1;
return 0;
}

浙公网安备 33010602011771号