【ACWing】1010. Intercepting missile

Subject address:

https://www.acwing.com/problem/content/1012/

A certain country has developed a missile interception system in order to defend against enemy missile attacks. However, this missile interception system has a flaw: Although its first shell can reach any height, each subsequent shell cannot be higher than the previous one. One day, the radar caught an enemy missile attack. Since the system is still in the trial phase, there is only one system, so it may not be able to intercept all missiles. Enter the altitude of the missiles in turn (the altitude data given by the radar is not greater than 30000 300003 0 0 0 0 is a positive integer, the number of missiles does not exceed1000 10001 0 0 0 ), calculate how many missiles this system can intercept at most, and how many sets of such missile interception systems are required to intercept all missiles.

Input format:
one line, input the altitude of the missiles in turn.

Output format: The
first line contains an integer, indicating the maximum number of missiles that can be intercepted. The second line contains an integer indicating the minimum number of systems to be equipped to intercept all missiles.

Data range:
the altitude data given by the radar is not more than 30000 300003 0 0 0 0 is a positive integer, the number of missiles does not exceed1000 10001000

The maximum number of missiles that can be intercepted is actually the longest non-strict descent subsequence. To intercept all missiles, it is actually to ask how many non-strictly descending sub-sequences the missile's height sequence can be divided into at least. This question is actually the application of the anti-chain decomposition theorem (refer to https://blog.csdn.net/qq_46105170 /article/details/108616895 ), the theorem is: the number of anti-chain decompositions with the least partial order set is equal to the length of the longest chain. In this question, in fact, the minimum number of decompositions of a non-strictly descending subsequence is equal to the length of its longest strictly ascending subsequence. There is a time complexity O (n log ⁡ n) O(n\log n)O ( nlogn ) the anti-chain decomposition algorithm, the general approach is to use an arrayfff Maintain the last number of all anti-chains (each anti-chain is a non-strictly descending sequence), and then come up with a new numberxxWhen x , findffThe smallest of f is greater than or equal toxxThe number of x , usexxReplace with x ; if there is no such number, open a new anti-chain, namelyxxx is an anti-chain by itself. It can be proved by mathematical induction thatfff is a monotonous rise, so it can be done by dichotomy. To prove the correctness of the algorithm, consider the optimal solution and the first different operation of the above method, and put the optimal solution inxxThe sequence formed by x and subsequent numbers, andxx in theabove solutionThe sequence formed by x and subsequent numbers is exchanged. After the exchange, it is still the optimal solution (because the number of anti-chains has not changed), so the optimal solution can be adjusted several times to become the above solution, which proves that the above solution is The smallest division of anti-chain decomposition. Finding the longest non-strictly descending subsequence can be done with dynamic programming (of course, it can also be done with anti-chain decomposition, and the answer is the minimum number of decompositions of strictly ascending subsequences). code show as below:

#include <iostream>
using namespace std;

const int N = 1010;
int a[N];
int f[N];
int n;

int main() {
    
    
    while (cin >> a[n]) {
    
    
        n++;
    }

    int res = 0;
    for (int i = 0; i < n; i++) {
    
    
        f[i] = 1;
        for (int j = 0; j < i; j++)
            if (a[i] <= a[j])
                f[i] = max(f[i], 1 + f[j]);
        res = max(res, f[i]);
    }

    cout << res << endl;

    int idx = 1;
    f[0] = a[0];
    for (int i = 1; i < n; i++) {
    
    
    	// f是单调增的,用二分找到第一个大于等于a[i]的数的下标,找不到就新开一个反链
        int l = 0, r = idx - 1;
        while (l < r) {
    
    
            int m = l + (r - l >> 1);
            if (f[m] > a[i]) r = m;
            else l = m + 1;
        }

        if (f[l] >= a[i]) f[l] = a[i];
        else f[idx++] = a[i];
    }

    cout << idx << endl;

    return 0;
}

Time complexity O (n 2) O(n^2)O ( n2) n n n is the number of missiles, spaceO (n) O(n)O ( n )

Guess you like

Origin blog.csdn.net/qq_46105170/article/details/114221798