Educational Codeforces Round 119 (Rated for Div. 2)

A - Equal or Not Equal

题目大意

E表示和下一个数值相等, N表示不相等
问 这个字符串所表达的数组是否合法

思路

有一些并查集的意思
但是有一些特殊的地方,

  • 如果全部都是E那自然不用说
  • 如果想把字符串拆成两个或以上的数组, 那么两个数组首位相连时必然会产生两个N, 而只有一个N的就说明不合法
    所以
    只要有两个以上的N, 那么这个字符串就必然合法, 相对的, 只有一个的时候就不合法

代码

#include <iostream>
 
using namespace std;
 
const int N = 50 + 10;
 
int n;
string str;
 
int main() {
    int T;
    cin >> T;
    while (T --) {
        cin >> str;
        int cnt = 0;
        for (auto i : str) if (i == 'N') cnt ++;
        if (cnt == 1) puts("NO");
        else puts("YES");
    }
    return 0;
}

B - Triangles on a Rectangle

题目大意

给你一个宽为W, 高为H的矩形, 还有四条边上的点, 问可以构成两个点在同一条边的最大的三角形的面积是多少
题目要的是面积的二倍

思路

三角形的面积 = 底 * 高 * 2

  • 高的话, 我们可以直接选择对面那条边上的点, 这样点可以随便选, 而高一定为矩形的宽或者高
  • 底的话, 一定是选一条边上相距最远的点

代码

#include <iostream>
#include <algorithm>
 
using namespace std;
typedef long long LL;
 
const int N = 2e5 + 10;
 
LL w, h;
LL a[4][N];
 
int main() {
    int T;
    cin >> T;
    while (T --) {
        cin >> w >> h;
        for (int i = 0; i < 4; i ++) {
            cin >> a[i][0];
            for (int j = 1; j <= a[i][0]; j ++) cin >> a[i][j];
            sort(a[i] + 1, a[i] + a[i][0] + 1);
        }
        cout << max(
                h * max(a[0][a[0][0]] - a[0][1], a[1][a[1][0]] - a[1][1]),
                w * max(a[2][a[2][0]] - a[2][1], a[3][a[3][0]] - a[3][1])
                ) << endl;
    }
 
    return 0;
}

C - BA-String

题目大意

给你一个字符串, 可以在*的位置填写不超过k个的b字符, 问第x小的字符串是什么

思路

a分割开许多的*串, 在简化之后, 我们发现可以在a的左右填写不超过*串长度的b字符
而第x小, 必然是先在最后一个*串位置填写b, 而当*串达到最大时, 会在前一个*串填写一个, 并在这里重新填写
于是发现, 类似与一个每一位进制都不相同的加法, 而我们寻找的正是以他为进制的第x - 1

代码

(写的并不是很好, 如果有更好的可以分享给我)

#include <iostream>
#include <algorithm>
#include <cstring>
 
using namespace std;
typedef long long LL;
 
const int N = 2e3 + 10;
 
LL n, k, x;
string str;
LL a[N], b[N];
int idx, idx2;
 
void calc(LL n, LL k) {
    for (int i = n; i >= 0; i --) {
        b[i] = k % (a[i] + 1);
        k /= (a[i] + 1);
    }
}
 
int main() {
    int T;
    cin >> T;
    while (T --) {
        cin >> n >> k >> x;
        cin >> str;
        idx = idx2 = 0;
        memset(a, 0, sizeof a);
        memset(b, 0, sizeof b);
 
        for (int i = 0; i < n; i ++) {
            if (str[i] == 'a') {
                if (a[idx]) idx ++;
            }
            else a[idx] += k;
        }
 
        //for (int i = 0; i <= idx; i++) cout << a[i] << ' ';
 
        calc(idx, x - 1);
 
        //for (int i = 0; i <= idx; i ++) cout << b[i] << ' ';
 
        for (int i = 0; i < n; i ++) {
            if (str[i] == 'a') {
                if (i != 0 && str[i - 1] == '*') {
                    for (int i = 0; i < b[idx2]; i ++) cout << 'b';
                    idx2 ++;
                }
                cout << 'a';
            }
        }
        if (idx2 <= idx)
            while (idx2 <= idx) {
                for (int i = 0; i < b[idx2]; i ++) cout << 'b';
                idx2 ++;
            }
        cout << endl;
    }
 
    return 0;
}

D - Exact Change

题目大意

你有面值为1, 2, 3的钱币, 而商店有许多不同价格的商品, 问每次出门需要带的最少的钱币数量, 以满足不同的商品价格

思路

首先贪心, 一定是取最多数量的3钱币
然后就要细细讨论了

可以对着其进行参考, 写错地方还请指正

代码

#include <iostream>
#include <algorithm>
 
using namespace std;
 
int main() {
    int T;
    cin >> T;
    while (T --) {
        int n;
        cin >> n;
        int a[n];
        int t1 = 0, t2 = 0, t3 = 0;
        for (int i = 0; i < n; i ++) {
            cin >> a[i];
            if (a[i] % 3 == 0) t3 = max(t3, a[i]); 
            if (a[i] % 3 == 1) t1 = 1;
            if (a[i] % 3 == 2) t2 = 1;
        }
        sort(a, a + n);
 
        int ans;
        if (a[n - 1] % 3 == 0) {
            ans = a[n - 1] / 3 + (t1 || t2);
        }
        else if (a[n - 1] % 3 == 2) {
            ans = a[n - 1] / 3 + 1 + t1;
        }
        else {
            ans = a[n - 1] / 3 + 1 + (t2 && (a[0] == 1 || t3 + 1 == a[n - 1]));
        }
        cout << ans << endl;
    }
    return 0;
}

E - Replace the Numbers

题目大意

在很多操作过后, 求数组最后的值为多少

  • 1 x, 表示插入x
  • 2 x y 表示将之前所有的x变为y

思路

听说有维护数值关系, 和维护位置关系, 这里使用的是维护位置关系
维护数据用不了传统的并查集?
在map<int, list>中存下当值为int时, 所有的位置list
list可以很方便的进行转移

代码

#include <iostream>
#include <algorithm>
#include <map>
#include <list>
#include <cstdio>
#include <unordered_map>
 
using namespace std;
 
const int N = 5e5 + 10;
 
int n, idx;
int a[N];
unordered_map<int, list<int> > q;
 
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i ++ ) {
        int op;
        scanf("%d", &op);
 
        if (op == 1) {
            int x;
            scanf("%d", &x);
            q[x].push_back(idx ++);
        }
        else {
            int x, y;
            scanf("%d%d", &x, &y);
            if (x == y) continue;
 
            auto it = q.find(x);
            if (it != q.end()) {
                q[y].splice(q[y].begin(), q[x]);
                q.erase(it);
            }
        }
 
        
    }
    for (auto &i : q) {
        for (auto &j : i.second)
            a[j] = i.first;
    }
    for (int i = 0; i < idx; i ++) printf("%d ", a[i]);
    return 0;
}
posted @ 2021-12-27 21:02  哇唔?  阅读(113)  评论(0编辑  收藏  举报