2020-11-08
dp
180C 1400
题目
原题链接:https://codeforces.com/problemset/problem/180/C
思路
题目大意:给定一个由大写和小写字母组成的字符串,字符串长度不超过1e5,现在有一操作,可以将其中任一字母的大小写改变,问要将这个字符串变成所有大写字母都在小写字母的前面的最小操作数,即先大写字母再小写字母(隐含了说也可以全大写字母或全小写字母)。
思路:唯一一道我可以说tjdl的题目,泪目。
好好看看题目,明显跟具体的字母是什么没有关系,只跟其是大写或者小写有关系。
最后要我们得到的结果是先大写字母再小写字母,思考若把所以大写字母置为0,小写字母置为1,则要我们变得是一个非递减数列。
好了,问题很明显了,改变一个由0和1数组的一些项,使这个数组变成一个非递减数列。
看到这里,明显,是要我们求这个数组的最长非递减子序列的长度了,然后答案应该就是数组长度减去这个长度了。
然后,你就会TLE。。。。
n的范围是1e5,而最正宗的最长非递减子序列的复杂度是n^2,必炸无疑。
再次思考,当我们当前拿到一个0,与其满足非递减子序列的前一个状态的也一定是0的状态。
当我们拿到一个1时,其前一个状态就可以是0或者1了,看谁大就好了。
然后的然后,注意到,可能的状态只有两个,是确定的!!!!!
可以祭出字典大法了,我们记录到当前这个点为止,其前面最大的0的状态的dp值和1的状态的dp值。
所以复杂度由n^2降为n:
for (int i = 1; i <= len; i++) {
dp[i] = 1;
if (a[i] == 0)
dp[i] = mp[0] + 1;