Hướng dẫn giải của [Beginner Free Contest 04] NUMBER


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Hướng dẫn giải

Dòng đầu là N; N số tiếp theo là A_i, số lá bài có giá trị i. Hai lá là một cặp nếu giá trị chênh nhau không quá 1, và mỗi lá chỉ thuộc một cặp. Đáp án được tính bằng cách duyệt các giá trị tăng dần.

Mô phỏng tham lam — ~O(N\log N)~

Duyệt các giá trị có lá bài theo thứ tự tăng dần, giữ số lá còn lại của giá trị trước (chỉ có thể là 0 hoặc 1 sau khi xử lý). Với giá trị hiện tại: ghép cặp chéo với lá còn lại của giá trị trước trước, rồi ghép các lá còn lại với nhau; lá lẻ được giữ lại cho giá trị sau. Nếu hai giá trị không liên tiếp thì không ghép chéo được.

Nếu chỉ nộp sub này: đúng 20/20 test. Đề không chia subtask nên chỉ viết 1 sub.

Chương trình hoàn chỉnh

Đây là lời giải đầy đủ, chỉ có một sub vì đề không chia subtask.

#include <bits/stdc++.h>
using namespace std;

// Moi cap la 2 la bai co gia tri chenh nhau <= 1. Cac cap khong duoc dung chung la bai.
// Cac gia tri xep thanh chuoi lien tiep. Duyet gia tri tang dan, mang "du" la so la bai
// cua gia tri truoc chua ghep duoc (toi da 1 la, vi phan con lai duoc ghep noi bo).
// Uu tien ghep cheo truoc (moi cap cheo dung 1 la cua moi gia tri), roi ghep noi bo.

// Chi co mot cach xu ly cho bai nay (khong co subtask), nen chi viet 1 sub.
// Dau vao: A_i la so la bai co gia tri i.
long long sub1(const map<long long, long long> &cnt) {
    long long ans = 0, carry = 0, prev = -10;
    for (auto &kv : cnt) {
        long long v = kv.first, c = kv.second;
        if (v != prev + 1) carry = 0;    // hai gia tri khong lien tiep thi khong ghep cheo duoc
        long long m = min(carry, c);     // ghep cheo voi la du cua gia tri truoc
        ans += m;
        c -= m;
        ans += c / 2;                    // ghep noi bo gia tri nay
        carry = c % 2;                   // con 1 la le thi giu lai de ghep voi gia tri sau
        prev = v;
    }
    return ans;
}

int main() {
    // Dong dau: N. N dong tiep theo: A_i = so la bai ghi gia tri i (i = 1..N)
    int n;
    cin >> n;
    map<long long, long long> cnt;
    for (int i = 1; i <= n; i++) {
        long long a;
        cin >> a;
        if (a > 0) cnt[i] = a;
    }
    cout << sub1(cnt) << endl;
    return 0;
}

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.