Codeforces Round #661 (Div. 3)A~D题解

发布于 2020-08-06  0 次阅读


A. Remove Smallest

思路:

注意到数据范围很小(1 ≤ a i ≤ 100 ),求得输入的数组中的最小值和最大值,从最小到最大走一遍,看是不是其中的每个值都有,若无则NO,全有则YES

AC Code:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
// #define TDS_ACM_LOCAL
int n, mi, mx, vis[109], a;
void solve(){
    cin>>n;
    mx=0, mi=INF;
    memset(vis, 0, sizeof(vis));
    for(int i=1; i<=n; i++){
        cin>>a;
        vis[a]=1;
        if(a>mx)    mx=a;
        if(a<mi)    mi=a;
    }
    int flag=0;
    for(int i=mi; i<=mx; i++){
        if(vis[i]==0)   {flag=1; break;}
    }
    if(flag)    cout<<"NO"<<endl;
    else    cout<<"YES"<<endl;
    return ;
}   

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    int T;
    cin>>T;
    while(T--)  solve();
    return 0;
}

B. Gifts Fixing

思路:

很明显的a和b数组最终变成的值为各自数组中的最小值,所以对于对于每个位置的变化次数很容易就可以得到,对于a和b的变换可以是a–也可以是b–,或者同时两个自减,所以a和b相应位置的操作次数即为两个分别操作次数中最大的那个,然后对所有的操作次数求和即为最小操作次数

AC Code:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
// #define TDS_ACM_LOCAL
const int N=59;
int n, a[N], b[N];
int mia, mib;
long long ans;
void solve(){
    cin>>n;
    ans=0;
    mia=mib=INF;
    for(int i=1; i<=n; i++){
        cin>>a[i];
        if(a[i]<mia)    mia=a[i];
    }
    for(int i=1; i<=n; i++){
        cin>>b[i];
        if(b[i]<mib)    mib=b[i];
    }
    for(int i=1; i<=n; i++){
        ans+=max(a[i]-mia, b[i]-mib);
    }
    cout<<ans<<endl;
    return ;
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    int T;
    cin>>T;
    while(T--)  solve();
    return 0;
}

C. Boats Competition

题目大意:

给你一个长度为n的数组,从中两两取值,相加的值必须相等,求取得的值对最多的对数

思路:

注意到数据范围很小1 ≤ n ≤ 50,所以我们可以直接枚举S的取值,从2到2 ∗ n,然后对于每个取值分别计算其中可以去到的对数的个数,求得最大值即可

AC Code:

#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;
// #define TDS_ACM_LOCAL
const int N=110;
int n, x, a[N], ans, cnt;
void solve(){
    cin>>n;
    memset(a, 0, sizeof(a));
    for(int i=0; i<n; i++)  cin>>x, a[x]++;
    ans=0;
    for(int i=2; i<=2*n; i++){
        cnt=0;
        for(int j=1; j<=i; j++) if(a[i-j])  cnt+=min(a[j], a[i-j]);
        ans=max(ans, cnt/2);    //除2是因为会取到两次
    }
    cout<<ans<<endl;
    return ;
}

int main(){
    ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    int T;
    cin>>T;
    while(T--)  solve();
    return 0;
}

D. Binary String To Subsequences

题目大意:

给你一个长度为n的包含0和1的字符串,请你求出其中最少的01子字符串(0和1交替出现)的个数并且求出每个位置的0和1应该是第几个子字符串的

思路:

可以分别用两个队列分别存以0结尾和以1结尾的子字符串,代码中用idx表示的子字符串个数
1、将1接到0结尾的子字符串后变成1,存到1的队列
2、将0接到1结尾的子字符串后变成0,存到0的队列
3、如果没有以0结尾的子字符串,就创建一个新的
4、如果没有以1结尾的子字符串,就创建一个新的

AC Code:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
// #define TDS_ACM_LOCAL
const int N=2e5 +9;
int n, x, a[N], idx;
string s;
void solve(){   
    cin>>n;
    cin>>s;
    idx=0;
    queue<int> q0, q1;
    for(int i=0; i<n; i++){                 //idx表示的子字符串的个数,所以idx++代表创建了一个新的子字符串
        if(s[i]=='0'){                      
            if(!q1.empty()){                //将0接到1结尾的子字符串后变成0,存到0的队列
                x=q1.front(); q1.pop();
                a[i]=x;
                q0.push(x);
            }
            else{                           //如果没有以1结尾的子字符串,就创建一个新的
                a[i]=++idx;
                q0.push(idx);
            }
        }
        else{
            if(!q0.empty()){                //将1接到0结尾的子字符串后变成1,存到1的队列
                x=q0.front(); q0.pop();
                a[i]=x;
                q1.push(x);
            }   
            else{                           //如果没有以0结尾的子字符串,就创建一个新的
                a[i]=++idx;
                q1.push(idx);
            }
        }
    }
    cout<<idx<<endl;
    for(int i=0; i<n; i++)  cout<<a[i]<<" ";
    cout<<endl;
    return ;
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    int T;
    cin>>T;
    while(T--)  solve();
    return 0;
}


平平无奇的大学在读本科生