Codeforces Round 972(Div.2)A+B

Codeforces Round 972(Div.2)A+B+C

昨天晚上做了Codeforces Round 972(Div.2)的A、B两道题,今天补一下思路。

题目来源:https://codeforces.com/contest/2005

A. Simple Palindrome

题目描述

在这里插入图片描述

输入输出样例及解释

在这里插入图片描述

思路

说穿了这道题目的意思就是使用aeiou五个字母来构造给定长度n的字符串,使得字符串中所包含的回文子串最少。

显然使aeiou中所有相同的字母排列在一起,可以使得最终生成字符串中所包含的回文子串最少,比如当n=6的情况下,aaeiou是最优解,而当n=10的情况下,aaeeiioouu是最优解。显然,当n<5时,比如n=4时,不出现重复的字符是最优解,比如aeio

因此现在的问题转换为,如何快速地在给定n的情况下按要求输出字符。这一部分非常偏向于工程,从codeforces的官方题解中学习到了很多,在这里做一下记录。

#include <iostream>
#include <string>
#include <vector>
using namespace std;

const string VOWELS = "aeiou";

int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);

    int t;
    cin >> t;

    while(t --) {
        int n;
        cin >> n;
        vector<int> v(5, n/5);      // 使用v来记录字符输出的次数, 初始化为n/5
        for(int i=0; i<n%5; i++) {  // 以19为例, 19/5 = 3, 余数为4, 余数归到a, e, i, o四个字符当中
            v[i] ++;                // 使得最终的输出为aaaaeeeeiiiioooouuu共19位
        }
        for(int i=0; i<5; i++){     // 遍历五个字符
            for(int j=0; j<v[i]; j++) { // 按次数输出对应字符
                cout << VOWELS[i];
            }
        }
        cout << endl;
    }
    return 0;
}

B1. The Strict Teacher (Easy Version)

题目描述

在这里插入图片描述

输入输出样例及解释

在这里插入图片描述

思路

这道题是B问题的简单版本,题目描述中明确有:m=2, q=1,意味着只有两个老师,并且目标只会处于一个位置。这样就使得问题分成了三种情况,分别是目标在两个老师左侧/右侧/中间。

对于前两种情况,最优解只可能是目标向着两边运动,而老师也同时向两边运动,答案为距离边界最近的老师与边界的距离。

而对于第三种情况,最优解只可能是目标在原地不动,因为无论它向哪个方向运动只会减小自己与老师的距离,因此这种情况的最终答案是老师之间的距离除以二。

#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

int main()
{
    int t;
    cin >> t;
    while(t --){
        int l, m, q;
        cin >> l >> m >> q;
        int x1, x2, y;
        cin >> x1 >> x2;

        if(x1 > x2) swap(x1, x2);
        
        while(q --){
            cin >> y;
            if (x1 <= y && y <= x2){
                cout << (x2 - x1) / 2 << endl;
            }
            else if (y < x1){
                cout << x1 - 1 << endl;
            }
            else {
                cout << l - x2 << endl;
            }
        }
    }
    return 0;
}

B2. The Strict Teacher (Hard Version)

这道题的题目描述和输入输出样例和Easy Version是相同的,区别在于B2当中的m和q是不固定的,相当于可能存在多于两个老师来追捕目标,而目标的位置也是不固定的,需要根据输入的q来具体分析。

思路

尽管m和q是不固定的,但是解决问题的思路是类似的,仍然分为三种情况,即目标在老师的左侧、右侧和中间。前两种情况与B1相同,而第三种情况略有不同,因为老师的数目可能是大于2的。因此显然要找到将目标位置夹在中间的距离目标最近的两个老师。

这里需要先对老师的位置排个序,再使用二分查找来找到不大于目标位置的最后一个位置a不小于目标位置的第一个位置b,该情况下的最终答案即为 ( b − a ) / 2 (b - a) / 2 (ba)/2

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;

int t;
int n, m, q;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> t;
    while(t--) {
        cin >> n >> m >> q;
        vector<int> p(m);
        for(int i=0; i<m; i++){
            cin >> p[i];
        }
        sort(p.begin(), p.end());   // 对教师的位置进行排序从而进行二分查找

        while(q --) {
            int x;
            cin >> x;
            int v = upper_bound(p.begin(), p.end(), x) - p.begin(); // 使用upper_bound查找不小于q的第一个位置, 
                                                                    // 如果查找失败则返回迭代器尾部
            if(v == 0)          cout << p[0] - 1 << endl;
            else if (v == m)    cout << n - p[m-1] << endl;
            else                cout << (p[v] - p[v-1]) / 2 << endl;
        }
    }
    return 0;
}

此处顺便对C++当中的upper_bound用法进行了练习,使用upper_bound可以快速地查找有序数组p中不小于x的第一个数在可迭代对象当中的位置。

本文想对C题也进行一下补题,但是看到C题涉及到动态规划的部分,这一部分我还没有复习到,暂时先放弃了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值