Codeforces Round 950 (Div. 3)

Codeforces Round 950 (Div. 3)

Codeforces Round 950 (Div. 3)
在这里插入图片描述

A. Problem Generator

题意:每组题由A~G的题目组成,现在已经有n个题目,需要组m组题目,最少需要添加多少题目;

思路:记录一下每种题目的数量,看距离m差多少即可;

AC code:

void solve() {
    int n, m; cin >> n >> m;
    string s; cin >> s;
    sort(s.begin(), s.end());
    map<char, int> mp;
    int cnt = 0;
    for (auto c : s) mp[c] ++;
    for (char c = 'A'; c <= 'G'; c ++) {
        if (mp[c] < m) cnt += m - mp[c];
    }
    cout << cnt <<endl;
}

B. Choosing Cubes

题意:n个正方体,初始下标为f的正方体为最爱,倒序排列后前k项是否可能出现最爱的正方体;

思路:记录最爱的正方体的数值以及每种正方体的大小,倒序排列后移除前k项看最爱的正方体数值是否可能存在即可;

AC code:

void solve() {
    int n, f, k; cin >> n >> f >> k;
    vector<int> a(n + 1);
    map<int, int> mp;
    for (int i = 1; i <= n; i ++) cin >> a[i], mp[a[i]] ++;
    int pos = a[f];
    int cnt = mp[pos];
    sort(a.begin() + 1, a.end(), greater<int>());
    for (int i = 1; i <= k; i ++) {
        mp[a[i]] --;
    }
    if (cnt == mp[pos]) cout << "NO" << endl;
    else {
        if (mp[pos]) cout << "MAYBE" << endl;
        else cout << "YES" << endl;
    }
}

C. Sofia and the Lost Operations

题意:最初给出n个整数序列a,以及m次的修改序列,每个序列对应两个元素c,d,修改操作为 a c a_c ac=d,现在已知序列a,d以及修改后的序列b,能否找出可能符合条件的序列c;

思路:

已经通过修改变为正确的元素,以及修改后依然正确的元素,在他们之前任意修改该元素不会影响最终的序列;

所以我们每次取出下标下标最大的需要修改的元素,再取出下标最大的相同元素,剩下的元素填充到已经修改的元素前面即可;

AC code:

void solve() {
    int n; cin >> n;
    vector<int> a(n + 1), b(n + 1);
    for (int i = 1; i <= n; i ++) cin >> a[i];
    for (int i = 1; i <= n; i ++) cin >> b[i];
    int m; cin >> m;
    map<int, priority_queue<int>> mp;
    vector<int> c(m + 1, -1), d(m + 1);
    for (int i = 1; i <= m; i ++) {
        cin >> d[i];
        mp[d[i]].push(i);
    }
    for (int i = 1; i <= n; i ++) {
        if (a[i] != b[i]) {
            if (mp[b[i]].empty()) {
                cout << "NO" << endl;
                return;
            } else {
                int t = mp[b[i]].top();
                mp[b[i]].pop();
                c[t] = i;
            }
        }
    }
    for (int i = 1; i <= n; i ++) {
        if (a[i] == b[i]) {
            if (!mp[b[i]].empty()) {
                int t = mp[b[i]].top();
                mp[b[i]].pop();
                c[t] = i;
            }
        }
    }
    int pos = -1;
    for (int i = m; i >= 1; i --) {
        if (c[i] == -1) {
            if (pos == -1) {
                cout << "NO" << endl;
                return;
            } else {
                c[i] = pos;
            }
        } else {
            pos = c[i];
        }
    }
    cout << "YES" << endl;
}

D. GCD-sequence

题意:一个长度为n的整数序列的GCD序列定义为长度为n-1的gcd(ai, ai+1)序列,现在最多允许删除原序列的一个元素,使得新的gcd序列非递减;

思路:

找到第一个不符合条件的gcd元素下标pos,可能的修改有删除pos -1,pos,pos + 1三种情况,枚举删除后的序列是否成立即可;

注意,当pos = n时,对于第n-1元素不存在去寻找n+2的元素,直接返回true;

AC code:

int gcd(int a, int b) {
    if (b) while ((a%=b)&&(b%=a)); return a + b;
}

bool delet(int pos) {
    int last = -1, l = 1;
    while (l < n) {
        if (l == pos) l ++;
        else if (l + 1 == pos) {
            if (l + 1 == n) return true;
            int ca = gcd(a[l], a[l + 2]);
            if (last == -1) last = ca;
            else if (last > ca) return false;
            last = ca;
            l ++;
        } else {
            int ca = gcd(a[l], a[l + 1]);
            if (last == -1) last = ca;
            else if (last > ca) return false;
            last = ca;
            l ++;
        }
    }
    return true;
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) cin >> a[i];
    int last = gcd(a[1], a[2]), pos = -1;
    for (int i = 2; i < n; i ++) {
        if (gcd(a[i], a[i + 1]) < last) {
            pos = i;
            break;
        } 
        last = gcd(a[i], a[i + 1]);
    }
    if (pos == -1) {
        cout << "YES" << endl;
        return;
    }
    if (delet(pos) || delet(pos - 1) || (pos < n && delet(pos + 1))) {
        cout << "YES" << endl;
        return;
    } 
    cout << "NO" << endl;
}

E. Permutation of Rows and Columns

题意:给出AB两个二维矩阵,是否有可能通过交换行和列的操作使得A矩阵等于B矩阵;

思路:以每个行列为一个集合,以每个行列的最小元素为基准,先把行按照B排列,再把列按照B排列,最后验证操作后的A序列是否等于B序列即可;

AC code :

void solve() {
    int n, m; cin >> n >> m;
    vector<vector<int>> a(n + 1, vector<int>(m + 1, 0));
    vector<vector<int>> b(n + 1, vector<int>(m + 1, 0));
    for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) cin >> a[i][j];
    for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) cin >> b[i][j];

    vector<vector<int>> c(n + 1, vector<int>(m + 1, 0));
    vector<vector<int>> d(n + 1, vector<int>(m + 1, 0));
    map<int, int> row, col;
    for (int i = 1; i <= n; i ++) {
        int mn = n*m;
        for (int j = 1; j <= m; j ++) mn = min(mn, b[i][j]);
        row[mn] = i;
    }
    for (int j = 1; j <= m; j ++) {
        int mn = n*m;
        for (int i = 1; i <= n; i ++) mn = min(mn, b[i][j]);
        col[mn] = j;
    }
    for (int i = 1; i <= n; i ++) {
        int mn = n*m;
        for (int j = 1; j <= m; j ++) mn = min(mn, a[i][j]);
        if (!row[mn]) {
            cout << "NO" << endl;
            return;
        }
        c[row[mn]] = a[i];
    }
    for (int j = 1; j <= m; j ++) {
        int mn = n*m;
        for (int i = 1; i <= n; i ++) mn = min(mn, c[i][j]);
        if (!col[mn]) {
            cout << "NO" << endl;
            return;
        }
        for (int i = 1; i <= n; i ++) d[i][col[mn]] = c[i][j];
    }
    for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
        if (d[i][j] != b[i][j]) {
            cout << "NO" << endl;
            return;
        }
    }
    cout << "YES" << endl;
}
  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值