终于本弱一次通关了一道研究生组别的题了[普及/提高?]
一道较为简单的双指针题,但一定有更好的解法.
小蓝有一个长度均为 n n n 且仅由数字字符 0 ~ 9 0 \sim 9 0~9 组成的字符串,下标从 0 0 0 到 n ? 1 n-1 n?1,你可以将其视作是一个具有 n n n 位的十进制数字 n u m num num,小蓝可以从 n u m num num 中选出一段连续的子串并将子串进行反转,最多反转一次。小蓝想要将选出的子串进行反转后再放入原位置处得到的新的数字 n u m n e w num_{new} numnew? 满足条件 n u m n e w < n u m num_{new}<num numnew?<num,请你帮他计算下一共有多少种不同的子串选择方案,只要两个子串在 n u m num num 中的位置不完全相同我们就视作是不同的方案。
注意,我们允许前导零的存在,即数字的最高位可以是 0 0 0,这是合法的。
输入一行包含一个长度为 n n n 的字符串表示 n u m num num(仅包含数字字符 0 ~ 9 0 \sim 9 0~9),从左至右下标依次为 0 ~ n ? 1 0 \sim n-1 0~n?1。
输出一行包含一个整数表示答案。
210102
8
一共有 8 8 8 种不同的方案:
对于 20 % 20\% 20% 的评测用例, 1 ≤ n ≤ 100 1 \le n \le 100 1≤n≤100;
对于 40 % 40\% 40% 的评测用例, 1 ≤ n ≤ 1000 1 \le n \le 1000 1≤n≤1000;
对于所有评测用例, 1 ≤ n ≤ 5000 1 \le n \le 5000 1≤n≤5000。
给个免费的赞吧谢谢ヽ( ̄ω ̄( ̄ω ̄〃)ゝ
写在前面:本来以为需要判定符号,后面删了符号判断也能过,说明不需要判断
#include<bits/stdc++.h>
using namespace std;
string s;int counter;
inline bool reverse_xyz(const string& str){
for(auto its=str.cbegin(),ite=str.cend()-1;its<ite;--ite,++its){
if(*its==*ite)continue;
else if(*its<*ite)return false;//不值得颠倒
else return true;//值得颠倒
}
return false;
}
int main(){
cin>>s;
for(int i=0;i<s.size()-1;++i)for(int j=2;j<s.size()-i+1;++j){
if(reverse_xyz(s.substr(i,j)))++counter;
}
cout<<counter;
}
note:
//重复量有点大
//可以优化:哈希表,记忆化,改日实现
//考虑如果当前子串的首尾已经比较出结果
//1.若不值得换,则大于等于当前子串尾的一定 不值得
//2.若值得去换,则小于等于当前子串尾的一定 也值得
/*
eg:
例如本题需要改变后小于则值得
12234
第一轮传入子串32,发现不值得(21101!<12101),并且向后查找第一个小于尾部元素2,find_if()没有,则以该位置起始的所有子串都不值得去换
23202
第一轮传入子串23,发现不值得(32102!<23102),则大于等于3的一定也不值得,故向后查找第一个小于3的元素再比较,find_if()找到2(序列第三的2),发现也不值得,则向后找第一个小于2的元素再比较,得到0,发现值得
12345
第一轮传入12,显然21!<12,且尾巴是2,后面没有一个小于2的,故序列第1的元素没有匹配的,直接返回,节省循环判断时间
如果值得,则可以hash表一下对应的序列第几桶,然后后面的遍历就不会到它.
*/
#include<bits/stdc++.h>
using namespace std;
string s;int counter;
inline bool reverse_xyz(const string& str){
for(auto its=str.cbegin(),ite=str.cend()-1;its<ite;--ite,++its){
//双指针内移,若相等继续判定,不相等则输出该子串值不值得reverse
if(*its==*ite)continue;//相等则双指针内移
else if(*its<*ite)return false;//不值得颠倒
else return true;//值得颠倒
}
return false;
}
//负数情况
inline bool reverse_xyf(const string& str){
for(auto its=str.cbegin(),ite=str.cend()-1;its<ite;--ite,++its){
if(*its==*ite)continue;
else if(*its>*ite)return false;//首位是负号则是大于
else return true;
}
return false;
}
int main(){
cin>>s;
//如果是纯数字,默认为无符号正数
if(isdigit(s[0]))for(int i=0;i<s.size()-1;++i)for(int j=2;j<s.size()-i+1;++j){
if(reverse_xyz(s.substr(i,j)))++counter;//根据左右端点传入子串
}
else if(s[0]=='+')for(int i=1;i<s.size()-1;++i)for(int j=2;j<s.size()-i+1;++j){
if(reverse_xyz(s.substr(i,j)))++counter;
}
else if(s[0]=='-')for(int i=1;i<s.size()-1;++i)for(int j=2;j<s.size()-i+1;++j){
if(reverse_xyf(s.substr(i,j)))++counter;
}
cout<<counter;
}
//s.substr(i,j);
//包括i索引的字符在内及其后j-1个字符组成j个字符长度