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;
}
posted @ 2025-04-16 20:02  LteShuai  阅读(37)  评论(0)    收藏  举报