Contestant'. Rank 1622. Rating +15.

A. Grasshopper on a Line

题意

给定一个数轴,终点 \(x\) 以及一个整数 \(k\),定义一次操作为从当前位置向右移动 \(p\) 格,满足 \(p\mod k \neq 0\)。输出从原点走到 \(x\) 所需的最小的操作数以及方案。

思路

如果 \(x\) 不能被整除,一步即达。

可以被整除的话,\(x - 1\) 肯定不会被整除(互质),因此选择先走一格再走 \(x - 1\) 格。

时间复杂度:\(O(1)\)

对应AC代码

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define pii pair<int, int>
#define pci pair<char, int>
#define fs first
#define sc second
#define pb emplace_back
#define all(x) x.begin(),x.end()

const int N = 1e7 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    int n, k;
    cin >> n >> k;
    if(n % k == 0) cout << 2 << '\n' << 1 << ' ' << n - 1 << '\n';
    else cout << 1 << '\n' << n << '\n';
}

signed main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while(t --) solve();
}

和之前的某个签到题很像

B. Comparison String

题意

给定一个由 \(<\)\(>\) 组成的字符串,定义如果第 \(i\) 位为 \(<\),那么 \(a_i < a_{i + 1}\),否则 \(a_i > a_{i + 1}\)

构造一个满足条件的序列 \(a\),输出不同数字的最少个数。

思路

很显然,如果出现了单调的区间,那么这段长为 \(k\) 的区间内一定有 \(k\) 格不同的数字,不同单调序列的元素可以共用,因此答案即为所有单调区间的长度的最大值。

时间复杂度:\(O(n)\)

对应AC代码

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define pii pair<int, int>
#define pci pair<char, int>
#define fs first
#define sc second
#define pb emplace_back
#define all(x) x.begin(),x.end()

const int N = 1e7 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    int ans = 1, sum = 1;
    for(int i=0;i<n;i++){
        if(s[i] == s[i + 1]) sum ++;
        else sum = 1;
        ans = max(ans, sum);
    }
    cout << ans + 1 << '\n';
}

signed main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while(t --) solve();
}

不可模拟,模拟有坑

C. Best Binary String

题意

给定一个二进制字符串,其中有若干位被替换为 \(?\)

定义对于一个二进制串,一次操作为选定一个区间并将这个区间内的数字左右翻转,代价为 \(1\)

输出一种 \(?\) 的替换方案,使让字符串不递减的代价最小。

思路

首先,如果将问号替换成前面的数,就可以让代价最小,这是显然的。

那么,如果第一个是问号,显然我们不希望再多一个 \(1\),因此直接放 \(0\)

反过来也行,最后一位放 \(1\)

时间复杂度:\(O(n)\)

对应AC代码

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define pii pair<int, int>
#define pci pair<char, int>
#define fs first
#define sc second
#define pb emplace_back
#define all(x) x.begin(),x.end()

const int N = 1e7 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    string s;
    cin >> s;
    int n = s.size();
    if(s[0] == '?') s[0] = '0';
    char pre = s[0];
    for(int i=1;i<n;i++){
        if(s[i] == '?'){
            s[i] = pre;
        }else pre = s[i];
    }
    cout << s << '\n';
}

signed main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while(t --) solve();
}

一开始写的思路差点就对了,淦

D. Bracket Coloring

题意

给定一个由左右括号组成的字符串,定义满足下面条件任意一个即为 "美丽的":

  1. 符合语法规则;

  2. 将字符串逆序输出后得到新的字符串,新的字符串满足语法规则

定义可将字符串涂色,涂色后,任取一种颜色,将该颜色的所有括号拿出后得到的新字符串都是 "美丽的"。

输出最少颜色种数,以及对应的一种方案。

需满足涂入的颜色编号小于等于颜色种数。

思路

我们不妨直接模拟,用队列存上一个最近的可配对的括号,因而我们进行分讨:

  1. 遇到 \((\): 如果上一个括号为 \((\),那么放入队列中等待配对; 如果上一个括号为 \()\),那么配对,并归入第一种颜色

  2. 遇到 \()\): 如果上一个括号为 \()\),那么放入队列中等待配对; 如果上一个括号为 \((\),那么配对,并归入第二种颜色

可以证明,最多只需两种颜色,如果上述操作后仍有没有配对的括号,那就无解。

时间复杂度:\(O(n)\)

对应AC代码

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define pii pair<int, int>
#define pci pair<char, int>
#define fs first
#define sc second
#define pb emplace_back
#define all(x) x.begin(),x.end()

const int N = 1e7 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    queue<pci> q1, q2;
    vector<int> ans(n, 1);
    bool f1 = false, f2 = false;
    for(int i=0;i<n;i++){
        char now = s[i];
        if(now == '('){
            if(q1.empty() || q1.front().fs == '(') q1.emplace(now, i);
            else{
                auto e = q1.front();
                q1.pop();
                ans[e.sc] = ans[i] = 2;
                f1 = true;
            }
        }else{
            if(q1.empty() || q1.front().fs == ')') q1.emplace(now, i);
            else{
                q1.pop();
                f2 = true;
            }
        }
    }
    if(q1.empty()){
        cout << (f1 && f2 ? 2 : 1) << '\n';
        if(f1 && f2) for(auto e : ans) cout << e << ' ';
        else for(int i=0;i<n;i++) cout << 1 << ' ';
        cout << '\n';
    }else cout << -1 << '\n';
}

signed main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while(t --) solve();
}

乱猜的居然过了(