Codeforces Round #767 (Div. 2)

A - Download More RAM

题目大意

给定n个内存条, 每个内存条可以增加\(b_i\)的内存, 但前提是你有足够的内存\(a_i\)去使用, 初始内存为k

思路

只要内存大于所要求的\(a_i\), 就可以使内存增加\(b_i\), 那么按照a排序贪心就好

代码

#include <iostream>
#include <algorithm>
 
using namespace std;
 
const int N = 110;
 
int n, k;
struct Node {
    int a, b;
}a[N];
 
int main() {
    int T;
    cin >> T;
    while (T --) {
        cin >> n >> k;
        for (int i = 1; i <= n; i ++ ) cin >> a[i].a ;
        for (int i = 1; i <= n; i ++) cin >> a[i].b;
        sort(a + 1, a + n + 1, [](Node a, Node b) {
            return a.a < b.a;
        });
 
        for (int i = 1; i <= n; i ++)
            if (a[i].a <= k) {
                k += a[i].b;
            }
        cout << k << endl;
    }
    return  0;
}

B - GCD Arrays

题目大意

给定一个去区间[l, r], 问经过k次操作之后, 能不能使所有数的最大公约数不为1
每次操作为删除两个数, 并将这两个数的乘积加入数组

思路

区间[l, r], 一串相连的数字, 那么他们的最大公约数除了1, 只能是2了, 又或者所有数合成了一个

  • 合成一个, 需要至少r - l + 1次, 这里有个特例就是左右端点相等, 那这两个端点就不能为1了
  • 最大公约数为2, 必须得相邻两个相互配对, 而且如果右端点为奇数的化, 那么右端点就必须和左边的那一组配对

代码

#include <iostream>
#include <algorithm>
 
using namespace std;
 
const int N = 110;
 
int n, k;
struct Node {
    int a, b;
}a[N];
 
int main() {
    int T;
    cin >> T;
    while (T --) {
        int a, b, c;
        cin >> a >> b >> c;
        if (a == b && a > 1) puts("YES");
        else if ((b - a + 1 + (b % 2)) / 2 <= c) puts("YES");
        else puts("NO");
    }
    return  0;
}

C - Meximum Array

题目大意

每次可以从头开始, 选取任意长度的原数组, 然后将这段序列的MEX加入新数组中, 问最后形成的新数组最大是多少

思路

首先原数组是一定要被遍历完的

  • 新数组最大, 一定是先将所有数可以凑出的最大的MEX加入
  • 然后从0到n, 一旦遇到断点, 就将断点加入答案
  • 如果是0缺失的化, 应该是加入剩下原数组长度的0加入答案
    然后是怎么样遍历
    我们可以枚举当前的MEX, 如果后面存在这个数, 那么MEX++, 如果不存在, 那么这个MEX就是断点
    预处理每个数的位置, 利用数组下标i来判断是否是否枚举完毕

代码

#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
 
using namespace std;
 
const int N = 2e5 + 10;
 
int n;
int a[N], b[N];
vector<int> idx[N];
vector<int> ans;
 
int main() {
    int T;
    cin >> T;
    while (T --) {
        cin >> n;
        ans.clear();
        for (int i = 0; i <= n; i ++) {
            idx[i].clear();
            b[i] = 0;
        }
 
        for (int i = 1; i <= n; i ++) {
            cin >> a[i];
            idx[a[i]].push_back(i);
        }
 
            int cnt = 0, i = 1;
            while (i <= n) {                                                         // 当没有枚举到数组末尾的时候
                //cout << ans.size() << ' ' << cnt << ' ' << i << endl;
                if (b[cnt] < idx[cnt].size()) {                                      // 如果当前的MEX在数组后面还有
                    i = max(i, idx[cnt][b[cnt]]);                                    // 将数组下标后移
                    b[cnt ++] ++;
                    if (cnt > n) {
                        for (int j = 0; j < cnt; j ++)                                // 所有数组下标之前的数, 都不能再进行访问
                            while (b[j] < idx[j].size() && idx[j][b[j]] <= i) b[j] ++;
                        ans.push_back(cnt);
                        cnt = 0;
                    }
                }
                else {
                    if (cnt == 0) {                                                    // 如果缺失的是0
                        while (i <= n) {
                            ans.push_back(0);
                            i ++;
                        }
                        break;
                    }
                    else {                                                              // 不是0, 缺失一个断点, 重新进行遍历
                        ans.push_back(cnt);
                        for (int j = 0; j < cnt; j ++)
                            while (b[j] < idx[j].size() && idx[j][b[j]] <= i) b[j] ++;
                        cnt = 0;
                        if (i == n) break;                                              // 数组已经到末尾就退出, 没有到就++, 继续进行下一轮的遍历
                        else i ++;
                    }
                }
            }
 
            cout << ans.size() << endl;
            for (auto j : ans) cout << j << ' '; cout << endl;
 
    }
    return  0;
}

D - Peculiar Movie Preferences

题目大意

给定n个长度不超过3的字符串, 问是否可以选取任意多个字符串来构成一个回文字符串

思路

主要是有长度不超过3这个限制, 这样我们就可以进行暴力的枚举, 回文串的长度无非是1, 2, 3, 4, 5, 6, 如果有更长的回文串的话, 我们一定可以删去其中的一部分

  • 长度为1的字符串, 一定就是回文串了
  • 长度为2的字符串, 要么本身是回文, 要么是存在一个字符串正好相反
  • 长度为3的字符串, 第一种还是本身是回文, 第二种是存在一个相反的字符串, 第三种是存在一个长度为2的字符串, 可以拼接到后面或者前面形成一个回文

代码

#include <iostream>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
 
#define x first
#define y second
 
using namespace std;
 
int n;
map<string, vector<int> > mp;
 
bool solve() {
    mp.clear();
 
    cin >> n;
    for (int i = 1; i <= n; i ++ ) {
        string x;
        cin >> x;
        mp[x].push_back(i);
    }
 
    for (auto i : mp) {
        if (i.first.size() == 1) {
            return true;
        }
        else if (i.first.size() == 2) {
            string x = i.first;
            reverse(x.begin(), x.end());
            if (mp.count(x)) return true;
        }
        else {
            string x = i.first.substr(0, 2); // 拼接到这个后面
            string y = i.first.substr(1, 2); // 拼接到这个前面
            string z = i.first;
            reverse(x.begin(), x.end());
            reverse(y.begin(), y.end());
            reverse(z.begin(), z.end());
 
            if (mp.count(x) && mp[x].back() > i.second.front()) return true;
            if (mp.count(y) && mp[y].front() < i.second.back()) return true;
            if (mp.count(z)) return true;
        }
    }
    return false;
}
 
int main() {
    int T;
    cin >> T;
    while (T --) {
        if (solve()) puts("YES");
        else puts("NO");
    }
}
上一篇:Xamarin Android 监听音量键(下)


下一篇:AndroidN新增物理按键[android7.1.2][msm8953]