Dynamic programming-(the longest non-declining subsequence)

Reference: https://oi-wiki.org/dp/basic/

O(n^2) algorithm

Scan from the beginning every time to find the best answer.

int a[MAXN], d[MAXN];
int dp() {
    
    
  d[1] = 1;
  int ans = 1;
  for (int i = 2; i <= n; i++) {
    
    
    for (int j = 1; j < i; j++)
      if (a[j] <= a[i]) {
    
    
        d[i] = max(d[i], d[j] + 1);
        ans = max(ans, d[i]);
      }
  }
  return ans;
}

O(nlogn) algorithm dichotomy

Refer to this article https://www.cnblogs.com/itlqs/p/5743114.html
Insert picture description here
then the code is as follows:

for (int i = 0; i < n; ++i) scanf("%d", a + i);
memset(dp, 0x1f, sizeof dp);
mx = dp[0];
for (int i = 0; i < n; ++i) {
    
    
  *std::upper_bound(dp, dp + n, a[i]) = a[i];
}
ans = 0;
while (dp[ans] != mx) ++ans;

Sample question: https://vijos.org/p/1303

description

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 experimental stage, there is only one system, so it may not be able to intercept all missiles.

format

Input format

There is only one line of input data, this line contains several data, separated by half-width commas, indicating the height of the missiles in turn (there is a maximum of 20 missiles, and the height is a positive integer not greater than 30,000).

Output format

There is only one line of output data, and this line contains two data, separated by a comma. The first data indicates the maximum number of missiles that this system can intercept; the second data indicates how many more such systems must be added to intercept all missiles.

Example 1

Sample input 1

389,207,155,300,299,170,158,65

Sample output 1

6,1

limit

Each test point has a time limit of 1 second.

Problem solving

Code

#include <algorithm>
#include <iostream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
const int maxn = 1e5 + 2;
int dp[maxn];  // dp[k]表示长度为k的不下降子序列末尾元素的最小值
// int minh[maxn];  //记录从第i项开始,剩下最大能消灭的导弹数量
vector<int> v;

int up_bound(int l, int r, int x) {
    
      //找到第一个大于x的数的下标
    while (l < r) {
    
    
        int mid = (r + l) / 2;
        if (x >= dp[mid])
            l = mid + 1;
        else
            r = mid;
    }
    return l;
}
int down_bound(int l, int r, int x) {
    
      //找到第一个小于等于x的数的下标
    for (int i = l; i <= r; i++)
        if (dp[i] <= x) return i;
    return r;
}

int main() {
    
    
    char ch;
    int n;
    while (true) {
    
    
        scanf("%d", &n);
        v.push_back(n);
        ch = getchar();
        if (ch == '\n') break;
    }

    v.push_back(0);
    reverse(v.begin(), v.end());

    int len = 1;
    dp[1] = v[1];
    for (int i = 2; i < v.size(); i++) {
    
      //求出最长不降子序列
        if (v[i] >= dp[len]) {
    
    
            dp[++len] = v[i];
        } else {
    
    
            int up = up_bound(1, len, v[i]);
            dp[up] = v[i];
        }
    }

    cout << len << ",";
    //第二问就出最大下降子序列
    len = 1;
    dp[1] = v[1];
    for (int i = 2; i < v.size(); i++) {
    
    
        if (v[i] < dp[len])
            dp[++len] = v[i];
        else {
    
    
            int down = down_bound(1, len, v[i]);
            dp[down] = v[i];
        }
    }

    cout << len - 1 << endl;

    return 0;
}
/*90 103 99 83 102 70 86 70 99 71*/

Guess you like

Origin blog.csdn.net/qq_45349225/article/details/109405029