Codeforces Round 894 div3 题解 | JorbanS

A. Gift Carpet

题意 从左到右选择四列,使得四列分别对应字母 v , i , k , a v,i,k,a v,i,k,a

string solve() {
    int n, m; cin >> n >> m;
    char s[N][N];
    char a[5] = "vika";
    int cnt = 0;
    for (int i = 0; i < n; i ++) cin >> s[i];
    for (int j = 0; j < m; j ++)
        for (int i = 0; i < n; i ++)
            if (s[i][j] == a[cnt]) {
                cnt ++;
                break;
            }
    if (cnt == 4) return yes;
    return no;
}

B. Sequence Game

题意 a a a 序列经过转换变成 b b b 序列,已知 b b b 序列,求任意一个可能的 a a a 序列

首先 b 0 ← a 0 b_0 ← a_0 b0a0,然后只要满足 a i − 1 ≤ a i a_{i-1}\le a_i ai1ai 就将 a i   p u s h _ b a c k a_i~push\_back ai push_back b b b 序列后面

void solve() {
    int n; cin >> n;
    vector<int> a(1);
    cin >> a[0];
    for (int i = 1; i < n; i ++) {
        int x; cin >> x;
        if (*(a.end() - 1) > x) a.push_back(x);
        a.push_back(x);
    }
    cout << a.size() << endl;
    for (auto i : a) cout << i << ' ';
    cout << endl;
}

C. Flower City Fence

题意 给出每个栅栏的高度(宽度为 1 1 1),问这个栅栏是否关于 y = x y=x y=x 对称

string solve() {
    int n; cin >> n;
    vector<int> a(n);
    for (auto &i : a) cin >> i;
    a.push_back(0);
    int idx = 0;
    for (int i = n - 1; i >= 0; i --) {
        int t = a[i] - a[i + 1];
        while (t --) if (a[idx ++] != i + 1) return no;
    }
    return yes;
}

D. Ice Cream Balls

题意 每两种球可以合成一种冰淇淋,且 ( i , j ) = ( j , i ) (i,j)=(j,i) (i,j)=(j,i)。特殊的,两个球 1 1 1 可以合成 ( 1 , 1 ) (1,1) (1,1)。问至少需要多少球能刚好合成 n n n 个冰淇淋

ll solve() {
    ll n; cin >> n;
    ll l = 0, r = 2e9;
    while (l < r) {
        ll mid = l + r + 1 >> 1;
        if (mid * (mid - 1) / 2 <= n) l = mid;
        else r = mid - 1;
    }
    ll res = l + (n - l * (l - 1) / 2);
    return res;
}

E. Kolya and Movie Theatre

题意 一共 n n n 天每天一场电影,最多看 m m m 场电影,每场电影的热度为 a i a_i ai,每次看电影的兴奋值为 a i − c n t ⋅ d a_i-cnt·d aicntd,其中 d d d 为给定常数, c n t cnt cnt 为距上次看电影的天数,求最终的兴奋值之和

题解 优先队列

ll solve() {
    int n, m, d; cin >> n >> m >> d;
    priority_queue<int, vector<int>, greater<int>> q;
    ll res = 0, sum = 0;
    for (int i = 1; i <= n; i ++) {
        int x; cin >> x;
        if (x <= 0) continue;
        if (q.size() < m) {
            sum += x;
            q.push(x);
        } else {
            sum += x;
            q.push(x);
            sum -= q.top();
            q.pop();
        }
        res = max(res, sum - (ll)i * d);
    }
    return res;
}

F. Magic Will Save the World

题意 n n n 个怪兽血量为 a i a_i ai,魔法师初始有 0 0 0 点水魔法和 0 0 0 点火魔法,每秒分别恢复 w , f w,f w,f 点,对于每个怪兽只能

法一 b i t s e t bitset bitset

int solve() {
    int n, w, f; cin >> w >> f >> n;
    bitset<N> b;
    b[0] = true;
    int sum = 0;
    for (int i = 1; i <= n; i ++) {
        int x; cin >> x;
        sum += x;
        b |= b << x;
    }
    int res = sum;
    for (int i = 0; i <= sum; i ++) {
        if (!b[i]) continue;
        int x = (i + w - 1) / w;
        int y = (sum - i + f - 1) / f;
        res = min(res, max(x, y));
    }
    return res;
}

法二 d p dp dp 因为是从二维优化到一维,因此 j j j 逆序枚举

int solve() {
    int n, w, f; cin >> w >> f >> n;
    vector<int> a(n);
    int sum = 0;
    for (auto &i : a) cin >> i, sum += i;
    vector<int> dp(sum + 1);
    dp[0] = 1;
    for (auto i : a)
        for (int j = sum; j >= i; j --)
            dp[j] |= dp[j - i];
    int res = sum;
    for (int i = 0; i <= sum; i ++) {
        if (!dp[i]) continue;
        int x = (i + w - 1) / w;
        int y = (sum - i + f - 1) / f;
        res = min(res, max(x, y));
    }
    return res;
}

你可能感兴趣的:(OI,题解,算法,数据结构)