牛客竞赛——dd爱科学1.0
题目描述
链接:https://ac.nowcoder.com/acm/contest/11211/A
来源:牛客网
大科学家dddddd最近在研究转基因白菜,白菜的基因序列由一串大写英文字母构成,dddddd经过严谨的推理证明发现,只有当白菜的基因序列呈按位非递减形式时,这株白菜的高附加值将达到最高,于是优秀的dddddd开始着手修改白菜的基因序列,dddddd每次修改基因序列的任意位需要的代价是111,dddddd想知道,修改白菜的基因序列使其高附加值达到最高,所需要的最小代价的是多少。
输入描述:
第一行一个正整数n(1≤n≤1000000)
第二行一个长度为n的字符串,表示所给白菜的基因序列
保证给出字符串中有且仅有大写英文字母
输出描述:
输出一行,表示最小代价
示例1
输入
5 ACEBF
输出
1
说明
改成ACEEF或者ACEFF,都只用改动一个字符,所需代价最小为1
解题思路
本题可以转换为求最长不递减子序列的长度len,最后用n 减去 len即可得出最小代价,不过我们这里不能用传统的动态规划来做,因为它的时间复杂度为N^2,在本题中会超时,所以我们要对其优化,这里我们采用二分来优化。
整个过程中,我们需要维护一个存储最长不递减子序列的数组,虽然数组中存储的最长不递减子序列可能不是最终的答案,但是其长度一定等于最终的最长不递减子序列的长度。
AC代码
1 import java.util.Scanner; 2 3 /** 4 * @Author LZP 5 * @Date 2021/6/3 20:31 6 * @Version 1.0 7 * <p> 8 * 5 9 * ACEBF 10 * 1 11 * 7 12 * CBBEDAC 13 * 4 14 */ 15 public class LISnLogn { 16 public static void main(String[] args) { 17 Scanner input = new Scanner(System.in); 18 int n = input.nextInt(); 19 char[] c = input.next().toCharArray(); 20 input.close(); 21 22 // 维护一个dp数组,最长不递减子序列的长度即为数组元素的个数 23 int[] dp = new int[100000]; 24 int len = 0; 25 dp[0] = -1; 26 for (int i = 0; i < n; i++) { 27 if (c[i] - 'A' >= dp[len]) { 28 dp[++len] = c[i] - 'A'; 29 } else { 30 // 二分 31 int l = 0; 32 int r = len; 33 while (l <= r) { 34 int mid = (l + r) >> 1; 35 int val = c[i] - 'A'; 36 if (dp[mid] > val) { 37 // 在两个数之间,就插入 dp[mid - 1] < val < dp[mid] 38 if (dp[mid - 1] <= val) { 39 dp[mid] = val; 40 break; 41 } 42 r = mid - 1; 43 } else { 44 l = mid + 1; 45 } 46 } 47 } 48 } 49 50 System.out.println(n - len); 51 } 52 }