链接:https://ac.nowcoder.com/acm/contest/11211/A
来源:牛客网
题目描述
大科学家dddddd最近在研究转基因白菜,白菜的基因序列由一串大写英文字母构成,dddddd经过严谨的推理证明发现,只有当白菜的基因序列呈按位非递减形式时,这株白菜的高附加值将达到最高,于是优秀的dddddd开始着手修改白菜的基因序列,dddddd每次修改基因序列的任意位需要的代价是111,dddddd想知道,修改白菜的基因序列使其高附加值达到最高,所需要的最小代价的是多少。
输入描述:
第一行一个正整数n(1≤n≤1000000)
第二行一个长度为n的字符串,表示所给白菜的基因序列
保证给出字符串中有且仅有大写英文字母、
输出描述:
输入一行,表示最小代价。
示例
输入:
5
ACEBF
输出:
1
解题思路:
查找需要更改的最少的字符个数,就是求字符串序列中的最长非递减子序列,即整个字符串中不用更改的最长序列,再用字符串长度n减去求得的最长非递减子序列即为答案。(二分查找+贪心算法)(也可以用dp,但是有可能会超时)
#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
char a[N],q[N];
int n,tail;
int find(char x)//二分查找
{
int l,r,mid;
l=1;
r=tail;
int s=-1;
while(l<=r)
{
mid=(l+r)/2;
if(x>=q[mid-1]&&x<=q[mid])
s=max(s,mid);
if(x>=q[mid])
l=mid+1;
else
r=mid-1;
}
return s;
}
int main()
{
scanf("%d",&n);
scanf("%s",a+1);//从a+1为开始存,便于初始化q[0]
q[0]='A'-1;//将q[0]初始化为比'A'还小的字符
tail=0;
for (int i=1;i<=n;i++)
if(a[i]>=q[tail])
q[++tail]=a[i];//将遍历到的字符存到q数组的后端
else//不能插入后端时
{
int x=find(a[i]);//二分查找a[i]能插入的位置
if(x!=-1)
q[x]=a[i];//如果查找到即可插入到所查找的位置
}
printf("%d\n",n-tail);//用字符串长度减去最长非递减子序列长度
return 0;
}