题目描述
小蓝有一个长度均为 n 且仅由数字字符 0∼9 组成的字符串,下标从 0 到 n−1,你可以将其视作是一个具有 n 位的十进制数字 num,小蓝可以从 num 中选出一段连续的子串并将子串进行反转,最多反转一次。小蓝想要将选出的子串进行反转后再放入原位置处得到的新的数字 numnew 满足条件 numnew<num,请你帮他计算下一共有多少种不同的子串选择方案,只要两个子串在 num 中的位置不完全相同我们就视作是不同的方案。
注意,我们允许前导零的存在,即数字的最高位可以是 0,这是合法的。
输入格式
输入一行包含一个长度为 n 的字符串表示 num(仅包含数字字符 0∼9),从左至右下标依次为 0∼n−1。
输出格式
输出一行包含一个整数表示答案。
样例输入
210102
样例输出
8
评测用例规模与约定
对于 20% 的评测用例,1 ≤ n ≤ 100;
对于 40% 的评测用例,1 ≤ n ≤ 1000;
对于所有评测用例,1 ≤ n ≤ 5000。
解题思路
根据题意遍历字符串中每个含两个字符及以上的子序列进行判断,模拟对反转前后的数字从高位开始比大小的过程。
根据从高位开始比大小的规则,在子序列前后各设置一个指针,从左指针开始向右表示反转前的数字,从右指针开始向左表示反转后的数字。
- 如果右指针的数字小于左指针的数字,则表示反转后的字符串比原字符串更小,结果加一,结束比较;
- 如果右指针的数字大于左指针的数字,则表示反转后的字符串比原字符串更小,结束比较。
- 如果右指针的数字等于左指针的数字,则表示暂时没比较出结果或反转前后字符串相等,继续比较或结束循环;
参考代码
#include<bits/stdc++.h>
using namespace std;
int main(){string num;int ans=0,len;cin>>num;len=num.length();for(int i=0;i<len;i++){for(int j=len-1;j>i;j--){int k=(j-i+1)/2;int l=i,r=j;while(k--){if(num[l]>num[r]){ans++;}if(num[l]!=num[r]){break;}l++;r--;}continue;}}cout<<ans;return 0;
}