总结:5.10晚VP一场,总体来说还算可以吧,AC了AB两题,C题还差点
A. Matching
题意就是看能表示的数字的数目
思路:看问号出现的位置,如果问号出现在第一位,则答案乘9,否则,答案乘10
AC代码:
#include<iostream>
using namespace std;
int main(){
int T,ans;
string s;
cin>>T;
while(T--){
cin>>s;
ans=1;
if(s[0]=='0'){
cout<<"0"<<'\n';
continue;
}
for(int i=0;i<=s.size();i++){
if(i==0&&s[i]=='?'){
ans=9;
}else if(s[i]=='?'){
ans*=10;
}
}
}
return 0;
}
B. Sort the Subarray
有坑!!!一开始想的不对,WA2了,只是算了最长上升序列,没有考虑到这一段是否进行修改
思路:首先找到更改后的序列和原序列不同的最长的左边和右边,然后从左边和右边分别向两边扩展,如果左面的数小于等于最左面的或者右边的数大于等于最右边的就加上这个数,否则停止
//有坑!!!注意这道题的思路!!!
#include<iostream>
using namespace std;
const int N=200005;
int a[N],b[N];
int main(){
int T,n,l,r,nmin,nmax;
bool f;
cin>>T;
while(T--){
f=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
if(a[i]!=b[i]){
if(!f){
l=i;
f=1;
}
r=i;
}
}
nmin=b[l];nmax=b[r];
for(int i=l-1;i>=1;i--){
if(b[i]>nmin){
break;
}
l--;
nmin=b[i];
}
for(int i=r+1;i<=n;i++){
if(b[i]<nmax){
break;
}
r++;
nmax=b[i];
}
cout<<l<<' '<<r<<'\n';
}
return 0;
}
C. Tear It Apart
一开始就是找规律,发现每个字符串都能每次删去奇数位置的字符或者偶数位置的字符,但是发现删去字符后的处理很麻烦,尤其是在判断是否还有不同的字符的时候,复杂度很高,所以只能另辟蹊径
思路:记录每个字符出现的位置,保留的字符从a开始逐个遍历,记录两个保留的字符之间的最大间距(或者开头或者结尾),最大间距log2即为答案(这个是推出的guilv)
1 1
2 2
3 2
4 3
5 3
6 3
7 3
8 4
9 4
10 4
11 4
12 4
13 4
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int main(){
int T,ans,nmax;
string s;
cin>>T;
while(T--){
ans=0x3f3f3f3f;
vector<int>a[30];
cin>>s;
for(int i=0;i<s.size();i++){
a[s[i]-'a'].push_back(i);
}
for(int i=0;i<26;i++){
if(!a[i].size()){
continue;
}
nmax=0;
if(a[i][0]!=0){
nmax=max(nmax,a[i][0]);
}
if(a[i][a[i].size()-1]!=s.size()-1){
nmax=max(nmax,(int)s.size()-a[i][a[i].size()-1]-1);
}
for(int j=1;j<a[i].size();j++){
nmax=max(nmax,a[i][j]-a[i][j-1]-1);
}
ans=min(ans,nmax);
}
//注意log的求法!!!
// if(ans==0){
// cout<<0<<'\n';
// }else if(log2(ans)==ceil(log2(ans))){
// cout<<ceil(log2(ans))+1<<'\n';
// }else{
// cout<<ceil(log2(ans))<<'\n';
// }
//或者这样写
if(!ans){
cout<<0<<'\n';
}else{
cout<<(int)log2(ans)+1<<'\n';
}
}
return 0;
}