zoukankan      html  css  js  c++  java
  • P1020 [NOIP1999 普及组] 导弹拦截

    nlogn解决最长上升/不下降/下降/不上升子序列问题。

    设f[len]表示子序列长度为len时序列最后一个数是什么。

    那么可以根据具体情况来讨论,一种是直接++len,将其存在数列最后,另一种是用更优的更新不优的。

    此题中第一问不难看出是求一个最长不下降子序列,而第二问,相当于求一个最长上升子序列:

    我们假定对于a[i]序列已经分成了k组,那么在这k组中,一定会在k+1组中找到一个数比k组中的某一个(几个)数大(否则可将k与k+1组合并),那么相当于k个组为一个单调递增的序列,求这个增序列的最大长度即为答案。

    自己总结如下:

    严格单调上升或下降子序列,找的时候用lower_bound,反之用upper_bound。(用cmp可以从找第一个大于/大于等于的数转为找第一个小于/小于等于的数)

    严格单调上升或下降子序列,用>或<,反之用>=或<=。

    (在下面程序中进行修改)

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=100005;
    typedef long long ll;
    int cnt,tot,n;
    int a[N],f[N],d[N];
    bool cmp(int a,int b){
    	return a>b;
    }
    int main(){
    	while(cin>>a[++n]);
    	n--;
    	memset(f,0x3f3f,sizeof(f));
    	for(int i=1;i<=n;i++){
    		if(a[i]<=f[cnt]) f[++cnt]=a[i];//不上升 
    		else f[upper_bound(f+1,f+cnt+1,a[i],cmp)-f]=a[i];
    		if(a[i]>d[tot]) d[++tot]=a[i];
    		else d[lower_bound(d+1,d+tot+1,a[i])-d]=a[i];
    	}
    	printf("%d
    %d",cnt,tot);
    	return 0;
    }
    //lower_bound会找出序列中第一个大于等于x的数
    
    //upper_bound会找出序列中第一个大于x的数
    
  • 相关阅读:
    ssm利用ajax上传图片和参数
    ssm+rabbitmq 分布式实例
    ssh免密
    springboot中aop的尝试
    springboot中自定义属性实体类和应用
    滑动门--------实现导航栏背景图自适应文字内容多少
    嵌套块元素垂直外边距的合并(塌陷)
    vue项目处理时间戳问题
    vue项目中遇到的登录超时
    标签显示模式
  • 原文地址:https://www.cnblogs.com/New-ljx/p/15350563.html
Copyright © 2011-2022 走看看