Practice.

A. Spell Check

题意

给定一个字符串,判断其是否为字符串 \(\mathtt{Timur}\) 任意排列后的字符串。

思路

我们用 \(map\) 存一下这 \(5\) 个字符的出现次数,如果都出现一次,并且长度为 \(5\),即可。

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

对应AC代码

#include <bits/stdc++.h>

using namespace std;

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

const int N = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    map<char, int> mp = {{'T', 0}, {'i', 0}, {'m', 0}, {'u', 0}, {'r', 0}};
    for(char e : s){
        if(mp.count(e)) mp[e] ++;
        else{
            cout << "NO\n";
            return;
        }
    }
    cout << ((mp['T'] == 1 && mp['i'] == 1 && mp['m'] == 1 && mp['u'] == 1 && mp['r'] == 1) ? "YES\n" : "NO\n");
}

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

B. Colourblindness

题意

对于一个蓝绿色盲,给定两串长度相等的 \(R, G, B\) 字符串,输出是否相同。

思路

\(G, B\) 视为 \(1\)\(R\) 视为 \(0\),枚举即可。

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

对应AC代码

#include <bits/stdc++.h>

using namespace std;

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

const int N = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    map<char, int> mp = {{'R', 0}, {'G', 1}, {'B', 1}};
    int n;
    cin >> n;
    string a, b;
    cin >> a >> b;
    for(int i=0;i<n;i++){
        if(mp[a[i]] != mp[b[i]]){
            cout << "NO\n";
            return;
        }
    }
    cout << "YES\n";
    return;
}

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

这就不得不提某个愚人节了(

C. Word Game

题意

对于 \(3\) 个人,给定每个人写下的单词数 \(n\),并给出每个人写下的单词,按照下面的方式给每个人计分,并输出每个人的分数:

对于某个人说出的某个单词:

  1. 如果这个单词只被 \(1\) 个人写下,那么这个人得 \(3\) 分;

  2. 如果这个单词被 \(2\) 个人写下,那么这两个人各得 \(1\) 分;

  3. 如果这个单词被 \(3\) 个人写下,那么所有人都不得分

思路

\(map\) 存一下出现次数,然后再枚举所有单词统计分数即可。

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

对应AC代码

#include <bits/stdc++.h>

using namespace std;

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

const int N = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    int n;
    cin >> n;
    vector<string> a(n), b(n), c(n);
    map<string, int> cnt;
    for(int i=0;i<n;i++){
        cin >> a[i];
        cnt[a[i]] ++;
    }
    for(int i=0;i<n;i++){
        cin >> b[i];
        cnt[b[i]] ++;
    }
    for(int i=0;i<n;i++){
        cin >> c[i];
        cnt[c[i]] ++;
    }
    int A = 0, B = 0, C = 0;
    for(auto e : a){
        if(cnt[e] == 1) A += 3;
        else if(cnt[e] == 2) A ++;
    }
    for(auto e : b){
        if(cnt[e] == 1) B += 3;
        else if(cnt[e] == 2) B ++;
    }
    for(auto e : c){
        if(cnt[e] == 1) C += 3;
        else if(cnt[e] == 2) C ++;
    }
    cout << A << ' ' << B << ' ' << C << '\n';
}

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

ctrl c + ctrl v

D. Line

题意

给定一个由 \(L, R\) 组成的字符串,定义 \(L\) 表示该位置左边有多少字符,\(R\) 表示该位置右边有多少字符(上述均不包含本身)。

定义字符串的 为各字符代表的数量之和。

现在,定义一次操作为选定一个字符,将其改为 \(L\)\(R\)。对于 \(k \in [1, n]\),输出最多执行 \(k\) 次操作后字符串 的最大值。

思路

这是一个很显然的贪心,如果我们不考虑操作次数,最后前一半的字符肯定是 \(R\),后一半的字符肯定是 \(L\)(若有奇数个,显然中间的字符的选择是无影响的)。

并且,我们可以贪心地认为,我们只要从两边开始向里修改,即可让 最大。

当然,如果次数过多了,我们随便挑一个字符将其改为本身即可。

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

对应AC代码

#include <bits/stdc++.h>

using namespace std;

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

const int N = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    int n;
    cin >> n;
    int ans = 0;
    string s;
    cin >> s;
    for(int i=0;i<n;i++) {
        char cur = s[i];
        if (cur == 'L') ans += i;
        else ans += n - i - 1;
    }
    int l = 0, r = n - 1, cnt = 0;
    while(l < r){
        if(s[l] == 'L'){
            ans -= l;
            ans += n - l - 1;
            cnt ++;
            cout << ans << ' ';
        }
        if(s[r] == 'R'){
            ans -= n - r - 1;
            ans += r;
            cnt ++;
            cout << ans << ' ';
        }
        l ++, r --;
    }
    for(int i=cnt;i<n;i++) cout << ans << ' ';
    cout << '\n';
}

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

简单的贪心 + 双指针

E. Counting Rectangles

题意

给定 \(n\)\(h_i \times w_i\) 的矩形。

现在,给定 \(q\) 次询问,每次询问给定四个整数 \(h_s\ w_s\ h_b\ w_b\),输出满足 \(h_s < h_i < h_b, w_s < w_i < w_b\) 的所有矩形的面积和。

思路

首先,根据题给范围,我们不可以在每次询问时都遍历一遍区间。

注意范围,我们需要的就是一个矩形范围内的所有矩形的面积和。

因而,我们考虑二维前缀和。

因为长度范围很小,我们直接开一个二维数组,\(a[h][w]\) 表示以原点和 \((h, w)\) 为对角顶点的矩形范围内所有矩形的面积和,套板子即可。

时间复杂度:\(O(n + 1e6 + q)\)

对应AC代码

#include <bits/stdc++.h>

using namespace std;

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

const int N = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    int n, q;
    cin >> n >> q;
    vector<vector<int>> sum(1010, vector<int>(1010, 0));
    for(int i=0;i<n;i++) {
        int h , w;
        cin >> h >> w;
        sum[h][w] += h * w;
    }
    for(int i=1;i<=1e3;i++)
        for(int j=1;j<=1e3;j++){
            sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
        }
    while(q --){
        int hs, ws, hb, wb;
        cin >> hs >> ws >> hb >> wb;
        cout << (sum[hb - 1][wb - 1] - sum[hs][wb - 1] - sum[hb - 1][ws] + sum[hs][ws]) << '\n';
    }
}

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

对,没错,我 \(tle\)

F. L-shapes

题意

给定一个由 "." 和 "*" 组成的矩阵,定义 "L型" 如下:

*.    .*    **    **
**    **    .*    *.

检查矩阵是否满足下面的条件:

  1. 只包含 "L型",不包含其他由 "*" 组成的图形;

  2. "L型" 中的 "*" 字符需满足以其为中心的 \(9\) 宫格里都没有 "*"(除了 "L型" 的其他 "*" 字符)

下面给出不满足条件 \(2\) 的例子:

..**       ....
*.*.       *.**
**..       ***.

思路

这是一个 \(2 \times 2\) 的图案,考虑数据范围,我们完全可以枚举所有 \(2 \times 2\) 的区域,判断其是否为 \(4\) 个图案的其中一种。

如果我们判定这是一个 "L型" 图案,我们就可以进行分讨,判断外围一圈中指定位置是否出现了 "*",如果有,直接输出 \(NO\)

在判定之时,如果是 "L型" 图案,我们顺便标记一下图案中的 "*",那么,最后如果出现未被标记的 "*",就是出现了 "非L型"。

下面用 "/" 表示需要判定的位置:

///.     .///     ////     ////
/*..     ..*/     /**/     /**/
/**/     /**/     ..*/     /*..
////     ////     .///     ///.

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

对应AC代码

#include <bits/stdc++.h>

using namespace std;

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

const int N = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    //直接按2x2扫
    int n, m;
    cin >> n >> m;
    vector<vector<char>> a(n + 2, vector<char>(m + 2, '.'));
    vector<vector<bool>> st(n + 2, vector<bool>(m + 2));
    for (int i = 1; i <= n; i++) {
        string s;
        cin >> s;
        for (int j = 1; j <= m; j++) a[i][j] = s[j - 1];
    }
    //tl tr
    //bl br
    for (int i = 1; i < n; i++)
        for (int j = 1; j < m; j++) {
            char tl = a[i][j], tr = a[i][j + 1], bl = a[i + 1][j], br = a[i + 1][j + 1];
            if (tl == '*' && tr == '.' &&
                bl == '*' && br == '*') {
                bool ok = true;
                ok &= a[i - 1][j - 1] != '*' && a[i - 1][j] != '*' && a[i - 1][j + 1] != '*';
                ok &= a[i][j - 1] != '*' && a[i][j + 2] != '*';
                ok &= a[i + 1][j - 1] != '*' && a[i + 1][j + 2] != '*';
                ok &= a[i + 2][j - 1] != '*' && a[i + 2][j] != '*' && a[i + 2][j + 1] != '*' && a[i + 2][j + 2] != '*';
                if (!ok) {
                    cout << "NO\n";
                    return;
                }
                st[i][j] = st[i + 1][j] = st[i + 1][j + 1] = true;
            }
            if (tl == '.' && tr == '*' &&
                bl == '*' && br == '*') {
                bool ok = true;
                ok &= a[i - 1][j] != '*' && a[i - 1][j + 1] != '*' && a[i - 1][j + 2] != '*';
                ok &= a[i][j - 1] != '*' && a[i][j + 2] != '*';
                ok &= a[i + 1][j - 1] != '*' && a[i + 1][j + 2] != '*';
                ok &= a[i + 2][j - 1] != '*' && a[i + 2][j] != '*' && a[i + 2][j + 1] != '*' && a[i + 2][j + 2] != '*';
                if (!ok) {
                    cout << "NO\n";
                    return;
                }
                st[i + 1][j] = st[i][j + 1] = st[i + 1][j + 1] = true;
            }
            if (tl == '*' && tr == '*' &&
                bl == '*' && br == '.') {
                bool ok = true;
                ok &= a[i - 1][j - 1] != '*' && a[i - 1][j] != '*' && a[i - 1][j + 1] != '*' && a[i - 1][j + 2] != '*';
                ok &= a[i][j - 1] != '*' && a[i][j + 2] != '*';
                ok &= a[i + 1][j - 1] != '*' && a[i + 1][j + 2] != '*';
                ok &= a[i + 2][j - 1] != '*' && a[i + 2][j] != '*' && a[i + 2][j + 1] != '*';
                if (!ok) {
                    cout << "NO\n";
                    return;
                }
                st[i][j] = st[i + 1][j] = st[i][j + 1] = true;
            }
            if (tl == '*' && tr == '*' &&
                bl == '.' && br == '*') {
                bool ok = true;
                ok &= a[i - 1][j - 1] != '*' && a[i - 1][j] != '*' && a[i - 1][j + 1] != '*' && a[i - 1][j + 2] != '*';
                ok &= a[i][j - 1] != '*' && a[i][j + 2] != '*';
                ok &= a[i + 1][j - 1] != '*' && a[i + 1][j + 2] != '*';
                ok &= a[i + 2][j] != '*' && a[i + 2][j + 1] != '*' && a[i + 2][j + 2] != '*';
                if (!ok) {
                    cout << "NO\n";
                    return;
                }
                st[i][j] = st[i][j + 1] = st[i + 1][j + 1] = true;
            }
        }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            if (a[i][j] == '*' && !st[i][j]) {
                cout << "NO\n";
                return;
            }
        }
    cout << "YES\n";
}

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

无脑大模拟,出题太缺德

G. Even-Odd XOR

题意

给定无重复数字的序列的长度 \(n\),构造该序列,满足奇数位上的所有数的异或值等于偶数位上所有数的异或值。

思路

因为 \(n\)\(2e5\) 级别的,那么我们只需找一个大于 \(2e5\)\(2\) 的次方 \(x\),然后我们按顺序在前 \(n - 2\) 个数中放入 \(1, 2, 3, \ldots\),并计算奇数位和偶数位各数的异或值,最后和 \(x\) 取异或后输出两个数即可。

当然,存在 \(n\) 为奇数的情况,不过因为任何数 和 \(0\) 异或值都不变,所以我们在前面塞一个 \(0\) 即可。

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

对应AC代码

#include <bits/stdc++.h>

using namespace std;

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

const int N = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;

void solve() {
    int n;
    cin >> n;
    int even = 0, odd = 0;
    if(n % 2 == 1 && n > 3){
        cout << "0 ";
        n --;
    }
    for(int i=1;i<=n-2;i++){
        cout << i << ' ';
        if(i % 2 == 0) even ^= i;
        else odd ^= i;
    }
    cout << (262144 ^ even) << ' ' << (262144 ^ odd) << '\n';
}

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

有人 wa on 1 好多次,我不说是谁