A. Red Versus Blue
题意:要求你构造一串字符串,只有‘R’和‘B’组成,告诉你总长度以及‘R’的数量和‘B’的数量,且‘R’的数量一定比‘B’多,且构造的字符串中要求所有连续‘R’的长度尽可能的短。
思路:‘B’有x个,那么就可以构造出x+1段,构造的时候注意每段‘R’的长度就行。
AC code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n, r, b;
void solve()
{
cin >> n >> r >> b;
int cnt=0;
int t=r/(b+1);
int tt=r%(b+1);
int x=0;
while(cnt<n){
x++;
for(int i=0;i<t && cnt<n;i++) cout<<"R",cnt++;
if(x<tt) cout<<"R",cnt++;
if(b>0){
cout<<"B";
b--;
cnt++;
}
}
cout<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while(T--)
{
solve();
}
return 0;
}
B. Bit Flipping
题意:给你一个二进制串,你有k次操作机会,且必须全部用完,每次操作可以选择一个下标i,使得s[i]保持不变,其它的全部取反,求k次操作机会所能构造的按字典序排序的最大二进制串。
思路:贪心策略就是从高位到低位,让1尽可能保持不变,让0尽量变为1,。我们可以发现,1进行奇数次翻转后变成0,0进行奇数次翻转后会变成1,偶数次则不变,所有当k为奇数时,对于1在k不减为0的情况下,要对它操作奇数次,这里选择最少的次数1次,这样它就会翻转(奇数-奇数=偶数)次从而保持不变,0就不需要操作,进行奇数次翻转自然会取反变为1,遍历到最后一位时,如果有k剩余,那么就对最后一位操作k次即可。k为偶数时同理。
AC code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
int n,k,a[N];
string s;
void solve(){
cin>>n>>k>>s;
for(int i=1;i<=n;i++) a[i]=0;
s='!'+s;
if(k&1){
for(int i=1;i<n;i++){
if(s[i]=='1'){
if(k){
a[i]++;
k--;
}else{
s[i]='0';
}
}else if(s[i]=='0'){
s[i]='1';
}
}
if(s[n]=='1'){
if(k%2==0){
s[n]='0';
}
}else{
if(k%2==0){
s[n]='1';
}
}
a[n]=k;
}else{
for(int i=1;i<n;i++){
if(s[i]=='0'){
if(k){
s[i]='1';
a[i]++;
k--;
}
}
}
if(s[n]=='1'){
if(k&1){
s[n]='0';
}
}else{
if(k&1){
s[n]='1';
}
}
a[n]=k;
}
for(int i=1;i<=n;i++){
cout<<s[i];
}
cout<<endl;
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
cout<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
C. Line Empire
题意:给定n个城市的位置(位置均大于0)且依次增大,一开始有一个首都位于0号点,然后我们每次可以花费a⋅|c1−c2|的代价进行迁都,其中c1是当前首都位置,c2是要迁都到的位置,a是一个迁都代价系数,前提是c2这个城市已经被占领了。我们还可以花费b⋅|c1−c2|占领位于c2位置的城市,但是不改变首都的位置,而且c1和c2之间不能有未被占领的城市(只能一个一个攻克),其中c1是首都的位置。问我们占领所有的城市所需要的最小代价。
思路:攻打第一个城市肯定不能迁移,直接攻克就好,而对于后面的城市,是选择移动到该城市的前一个城市再攻打呢?还是选择直接攻打?假设当前的首都位置为pos,对于第一种情况的代价是a*abs|c[i-1]-pos|+b*|c[i-1]-c[i]|,第二种情况的代价是b*|c[i]-pos|,很容易就想比较两者取最小值判断是否迁移,但是我们眼光要长远,假设我们后面还要占领j个城市,那么我们就要重复的花费j*b*|c[i-1]-pos|代价,这是不迁移所带来的的额外的代价,因此即使第一种情况的代价>第二种情况的代价,我们还需要将它们的差值与重复的花费代价进行比较,详情见代码。
AC code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
ll n,a,b,x[N];
void solve(){
cin>>n>>a>>b;
for(int i=1;i<=n;i++) cin>>x[i];
ll ans=x[1]*b;
ll pos=0;
ll cnt=n-2;
for(int i=2;i<=n;i++){
ll t=a*abs(x[i-1]-pos)+b*abs(x[i]-x[i-1]);
ll tt=b*abs(x[i]-pos);
if(t<=tt){
pos=x[i-1];
ans+=t;
}else if(t>tt && cnt*b*abs(x[i-1]-pos)>=t-tt){
cnt--;
pos=x[i-1];
ans+=t;
}else{
ans+=tt;
}
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}