入侵和反击 -hydro

前言

实际上就是洛谷P1020改了点题意,和其他题解看起来就很难和一大堆证明不一样,我找到了个很有意思和简洁的题解(from这里),一道普及组的题目确实不应该做的折磨麻烦的

分析

从题意可以得知,a国的导弹系统出故障,导致只能发射高度依次递减的导弹进行拦截。给出n架飞机,求出最小能够有多少的飞机存活。换个方向去想,导弹系统能够拦截的实际上就是一个不连续的,递减的,最长的子序列。求出能够拦截的,能存活的飞机就显而易见是 n - len。

下面要介绍一下这里要用到的一个函数

下面是参数
upper_bound(begin, len , value, cmp)
//而它的返回值是一个指针,因此用到值要加*

做法

遍历整个数组,当当前值比已选的值小的时候,正好能够加入这个不连续的递减序列,所以向后移动,len + 1。
image

而当当前的值比已经选的小的大的时候,插入已选序列当中,它能够插入的最大的地方。这时候长度不变,也就是,选这一项并不会导致已选序列变长从而影响结果。
image

当遍历完整个数组,就能得出最大的len,也就是被击落飞机的最大数目。这时候,拿n减去len,就是所求答案

代码

void solve()
{
    int n;
    cin >> n;
    vector<int> v(n + 10), temp(n + 10);
    for (int i = 1; i <= n; i++)
        cin >> v[i];
    int len = 1;
    temp[1] = v[1];
    for (int i = 2; i <= n; i++){
        if(temp[len] >= v[i])
            temp[++len] = v[i];
        else
            *upper_bound(temp.begin() + 1, temp.begin() + 1 + len, v[i],greater<int>()) = v[i];
    }
    cout <<n - len << endl;
    return;
}
posted @ 2024-01-26 03:00  应许方舟  阅读(29)  评论(0)    收藏  举报