B. Minimize Permutation Subarrays
分析:要使子排列最少,一个子排列一定要有1。所以我们把最大值放到1和2之间,这样从1到2就会包含整个数组,从而最少。如果最大值已经在1和2之间就直接输出两次最大值下标。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int a[N];
void slove(){
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int id1,id2,idn;
for(int i=1;i<=n;i++){
if(a[i]==1)id1=i;
if(a[i]==2)id2=i;
if(a[i]==n)idn=i;
}
if((idn<id1&&idn>id2)||(idn<id2&&idn>id1))cout<<idn<<" "<<idn<<endl;
else if((idn<id1&&id1<id2)||(idn>id1&&id1>id2))cout<<id1<<" "<<idn<<endl;
else if((idn<id2&&id2<id1)||(idn>id2&&id2>id1))cout<<id2<<" "<<idn<<endl;
}
signed main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}
B1. Bouquet (Easy Version)
分析:因为相同的数运算是一样的而且要考虑顺序,所以我们用map统计个数方便计算。
我们通过m/花瓣数得到每一种的最大值,因为每次只有两种花瓣,所以我们遍历一种就行,另一种通过m控制时刻保持尽可能大。
#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
using namespace std;
const int N=2e5+10;
int s[N];
void slove(){
int n,m;
cin>>n>>m;
map<int,int>mp;
for(int i=1;i<=n;i++)cin>>s[i],mp[s[i]]++;
int ans=0;
for(auto i:mp){
int a=min(i.se,m/i.fi);//第一个花瓣最多有多少个
int next=i.fi+1;
int b=0;
if(mp.count(next)){//统计第二个花瓣的个数
b=mp[next];
}
for(int j=0;j<=a;j++){
int op1=j*i.fi;
int k=(m-op1)/next;
k=min(k,b);//在取了一定量的第一种后第二种最多有多少
int op2=k*next;
ans=max(ans,op1+op2);
}
}
cout<<ans<<endl;
}
signed main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}
C. Best Binary String
分析:要使最少反转次数变成不降序排列,就要尽可能出现连续的相等字符可以整体反转减少次数。所以每个?和前面的字符相同即可,如果?在第一个那就等于0(因为要不降序)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int a[N];
void slove(){
string s;
cin>>s;
for(int i=0;i<(int)s.size();i++){
if(s[i]=='?'){
if(i==0)s[i]='0';
else s[i]=s[i-1];
}
}
cout<<s<<endl;
}
signed main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}
C. Sort
分析:一般像这种q次查询的都不会暴力重复操作,大概率是前缀或差分。