A. Beat The Odds
题意:给出n个数,每次操作可以删除一个数,最终使得序列中每相邻两个数之和为偶数,求最少操作数。
思路:要么只有奇数,要么只有偶数。取奇数个数和偶数个数的最小值即可。
AC code:
#include <bits/stdc++.h>
using namespace std;
int n,a[100010];
int main(){
int t;
cin>>t;
while(t--){
cin>>n;
int cnt1=0;
int cnt2=0;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]&1) cnt1++;
else cnt2++;
}
cout<<min(cnt1,cnt2)<<endl;
}
return 0;
}
B. Shoe Shuffling
题意:给你一个非下降序列,让你打乱这些数,使得每个数所在的位置不在原来的位置。当且仅当a[i]>a[j]时,这两个数可以交换,判断是否能够满足题意,如果可以满足题意,输出原来数的位置被交换后的位置,否则输出-1。
思路:当一个数仅出现一次时,一定不能满足题意,若每个数都出现两次以上则满足题意,交换下标即可。
AC code:
#include <bits/stdc++.h>
using namespace std;
int n,a[100010];
void solve(){
cin>>n;
vector<array<int,2>> v;
for(int i=0;i<=n+1;i++) a[i]=-1;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=2;i<=n-1;i++){
if(a[i]!=a[i-1] && a[i]!=a[i+1]){
cout<<-1<<endl;
return ;
}
}
if(a[1]!=a[2] || a[n-1]!=a[n]){
cout<<-1<<endl;
return ;
}
int i=1;
int cnt=1;
while(i<=n){
if(a[i]!=a[i+1]){
v.push_back({i,cnt});
i++;
cnt=1;
}else{
cnt++;
i++;
}
}
for(auto [x,y]:v){
cout<<x<<' ';
for(int i=x-y+1;i<=x-1;i++){
cout<<i<<' ';
}
}
cout<<endl;
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
赛时没有check a[1]和a[n],哭死。
C. Sum of Substrings
题意:给你一段01串,相邻两个数字组成一个十位数,求这n-1个十位数的最小值,有k次操作,每次可以交换相邻两个数。
思路:头部的1对答案的贡献为10,尾部的1对答案的贡献为1,中间的1 对答案的贡献为11,因此优先将1移到尾部,然后再考虑移动到头部。
AC code :
#include <bits/stdc++.h>
using namespace std;
int n,k;
string s;
int main(){
int t;
cin>>t;
while(t--){
cin>>n>>k>>s;
s='#'+s;
long long ans=0;
for(int i=1;i<n;i++){
int t=(s[i]-'0')*10+(s[i+1]-'0');
ans+=t;
}
int pos1=0,pos2=0;
for(int i=n;i>=1;i--){
if(s[i]=='1'){
pos1=i;
break;
}
}
for(int i=1;i<=n;i++){
if(s[i]=='1'){
pos2=i;
break;
}
}
if(pos1==0){
cout<<ans<<endl;
continue;
}
if(pos1==pos2){
if(pos1!=n){
if(k>=n-pos1){
ans-=10;
if(pos1==1){
ans++;
}
}else if(k>=pos2-1 && pos2!=1) ans--;
}
}else{
if(k>=n-pos1 && pos1!=n){
ans-=10;
k-=n-pos1;
}
if(k>=pos2-1 && pos2!=1){
ans--;
}
}
cout<<ans<<endl;
}
return 0;
}