题目描述
大科学家dddddd最近在研究转基因白菜,白菜的基因序列由一串大写英文字母构成,dddddd经过严谨的推理证明发现,只有当白菜的基因序列呈按位非递减形式时,这株白菜的高附加值将达到最高,于是优秀的dddddd开始着手修改白菜的基因序列,dddddd每次修改基因序列的任意位需要的代价是111,dddddd想知道,修改白菜的基因序列使其高附加值达到最高,所需要的最小代价的是多少。
输入描述:
第一行一个正整数n(1≤n≤1000000)
第二行一个长度为n的字符串,表示所给白菜的基因序列
保证给出字符串中有且仅有大写英文字母
输出描述:
输出一行,表示最小代价
示例1
输入
5 ACEBF
5
ACEBF
输出
1
1
说明
改成ACEEF或者ACEFF,都只用改动一个字符,所需代价最小为1
解题思路
转化成找最长递增序列(非严格),由于有时间限制,所有采用二分查找,而不是动态规划进行优化
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// Write your code here
let params = [];
while ((line = await readline())) {
let tokens = line.split(" ");
// let a = parseInt(tokens[0]);
// let b = parseInt(tokens[1]);
// console.log(a + b);
params.push(tokens);
}
// console.log(params)
let n = parseInt(params[0][0]);
let str = params[1][0];
// console.log(n,str)
// console.log('A'.charCodeAt(0)-'B'.charCodeAt(0))
// console.log("A"+1)
let arr = str.split("");
// console.log(arr)
let dp = []; // 使用二分法 维持一个最大非递减数组
let len = 0;
for (let i = 0; i < arr.length; i++) {
// 判断当前元素是否不小于dp的最大元素
if (i == 0 || arr[i].charCodeAt(0) >= dp[len - 1].charCodeAt(0)) {
dp[len] = arr[i];
len++;
} else {
// 找到dp中比它小的元素,然后更新它,原先长度保持不变,只是为未来可以在后面添加元素腾出了新的空间
let left = 0;
let right = len - 1;
let pos = -1;
while (left <= right) {
let mid = Math.floor((right + left) / 2);
if (dp[mid].charCodeAt(0) > arr[i].charCodeAt(0)) {
pos = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
if (pos != -1) {
// 替换掉原有的元素
dp[pos] = arr[i];
}
}
}
// console.log(dp)
console.log(arr.length - dp.length);
})();