导弹拦截-最长不下降子序列和不下降子序列个数-nlogn算法

题目

 

1.最长不下降子序列求法(我还没吃透,处于看懂觉得牛逼但是自己想不到的情况)

 

2.不下降子序列的个数

分析:

假设现在有n个序列了

当遇到一个新数时,只要之前任意一个序列的最小数比它高,就可以把它放进来了

那么它该插入哪个序列呢?如果插入最小数最大的序列(最小数为x)后面,下次遇到比较大但是又没有x大的数,就没办法插入了

我管这叫做浪费,因为小数就可以杀掉的怪你非得大数杀

所以应该插入它能插入的数中最小的数

即开一个数组序列的最小数,找到大于等于它的序列中最小数,代替这个数(这样看来应该弄一个优先队列??->不用,一边一定一比该数大于等于,一边一定比该数小,顺序无误)

 

3.lower_bound用法

 

4.输入

while(scanf("%d",  &t)!=EOF)

或者

#include<iostream>
#include<cstdio>
#include<algorithm>
#define R register
using namespace std;
const int N=100010;
int a[N],d1[N],d2[N],n;
inline bool read(int &x) {
    char c=getchar();
    if(c==EOF)return false;
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9') {
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return true;
}
int main() {
    while(read(a[++n]));n--;
    R int len1=1,len2=1;
    d1[1]=d2[1]=a[1];
    for(R int i=2; i<=n; i++) {
        if(d1[len1]>=a[i])d1[++len1]=a[i];
        else *upper_bound(d1+1,d1+1+len1,a[i],greater<int>())=a[i];
        if(d2[len2]<a[i])d2[++len2]=a[i];
        else *lower_bound(d2+1,d2+1+len2,a[i])=a[i];
    }
    printf("%d\n%d",len1,len2);
    return 0;
}
快速输入

 

5.AC题解

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int a[N], b[N];
int main() {
    int t;
    scanf("%d",  &t);
    int len1 = 1, len2 = 1;
    a[1] = b[1] = t;
    while(scanf("%d",  &t)!=EOF)
    {
        if(t<=a[len1]) a[++len1]=t;
        else
        {
            int pos = upper_bound(a+1,a+1+len1,t, greater<int>())-a;
            a[pos] = t;
        }
        if(t>b[len2]) b[++len2]=t;
        else
        {
            int pos = lower_bound(b+1, b+1+len2,t)-b;
            b[pos] = t;
        }
    }
    printf("%d %d\n",  len1, len2);
    return 0;
}
AC代码

 

posted @ 2021-02-08 10:52  bear_xin  阅读(139)  评论(0)    收藏  举报