A.Matching
题意
给你一个由数字和’?'组成的字符串 ?可以替换成0-9 中任何数字,问这个字符串可以匹配多少个数字。
思路
有几个问号就乘以十的几次方,最后减去当字符串第一个为问号的情况,即当第一位为0 其它问号组合的情况,即10的问号总数-1的次方
代码
#include <iostream>
#include <cmath>
using namespace std;
void solve();
int main(){
int t;
cin>>t;
while(t--){
solve();
}
}
void solve() {
string a;
cin>>a;
int cnt=0;
if(a[0]=='0'){
cout<<"0\n";
return ;
}
for (int i = 0; i < a.length(); ++i) {
if(a[i]=='?') cnt++;
}
int ans=pow(10,cnt);
if(a[0]=='?') ans-=pow(10,cnt-1);
cout<<ans<<endl;
}
B.Sort the Subarray ## 题意
已知一个数组a,我们可以选择它一个下标范围l,r进行升序排序,得到数组a2。 a=[6,7,3,4,4,6,5], 选定l=2,r=5,那么排序后的a2=[6,3,4,4,7,6,5]。
现给定数组a和a2,求出原来的下标范围l,r。 如果存在多组解,选择下标范围最长的;如果下标范围最长的有多组解,输出任意一解。
思路
分两种情况:
1.a[i]与a2[i]不相同,那这个下标一定在[l,r]范围内
2.a[i]与a2[i]相同,如果在相同的情况下,也在下标范围内,那这个数一定满足升序排列,从左向右看,最左边的相同的数在序列中 看下面a数组的1,即在升序序列中处在正确的位置,那么右边的序列中的数一定都大于这个数,那在一个数相同的情况下,怎么确定在序列中的数是否都大于它呢。
首先先确定一个升序序列,不相同的一定在序列中,如下 2-5 在序列中。
再将序列最左边的数与其左边的数比较,如果比序列中最小的数还小,即意味着这个数在序列中 右边也一样,只是比较是否比最大的数还大。
代码
#include <iostream>
using namespace std;
const int N=2*1e5+1;
int a[N];
int b[N];
void solve();
int main(){
int t;
cin>>t;
while(t--){
solve();
}
}
void solve() {
int t;
cin>>t;
for (int i = 1; i <= t; ++i) cin>>a[i];
for (int i = 1; i <= t; ++i) cin>>b[i];
int l=1,r=t;
while(l<=t&&b[l]==a[l]) l++;
while(r>0&&a[r]==b[r]) r--; //先确定一个升序序列
while(l>1&&b[l]>=b[l-1]) l--; //往左边扩
while(r<t&&b[r]<=b[r+1]) r++; //往右边扩
cout<<l<<" "<<r<<endl;
}
C.Tear It Apart
题意
给定一个字符串,操作多次后只剩下同一字符,每次操作消除不相邻的多个字符,求最小操作次数
思路
“abcdef” 每次消除不相邻的多个字符 如这里5个字符 每次消除一半的字符 第一次操作 变为2 第二次 变为1 第三次变为0 多写几个就可以看出 字符数 除以2的t-1次方为1 如5 除以 2的3-1次方 为1 n为字符数 t为操作数
n
/
2
t
−
1
=
1
n
=
2
t
−
1
l
o
g
2
n
+
1
=
t
n/2^{t-1}=1\\ n=2^{t-1}\\ log_2n+1=t
n/2t−1=1n=2t−1log2n+1=t
而最后留下哪一个字符 可以将a到z遍历一遍 看哪个的操作次数最少 而每个字符的操作数取决于最大区间 codeforcesc 要保留c字符 由两个区间 第一个c与第二个c构成一个区间 第二,三个构成一个区间 取决于第一个最大区间长度 注意如果最后一个不是c 在循环后要单独处理这种情况
代码
#include <iostream>
#include<cmath>
using namespace std;
const int N=2*1e5+1;
void solve();
int main(){
int t;
cin>>t;
while(t--){
solve();
}
}
void solve() {
string s;
cin >> s;
int ans=0x3f; //ans要取最小值 先初始化为最大数
for (char i = 'a'; i <= 'z'; i++) {
int l = 0;
int t = 0;
for (int j = 0; j < s.length(); ++j) {
if (s[j] == i) { //l为区间长度
t = max(t, (int) log2(l) + 1);
l = 0;
} else l++;
}
t = max(t, (int) log2(l) + 1);
/*单独处理最后一个区间 如上的codeforces*/
ans = min(ans, t); //取保留任一字符中最小操作数
}
cout << ans << endl;
}