Thứ Bảy, 4 tháng 7, 2026

Một số bài tập C _C++ NC 2026P15

 map là gì?

map trong C++ là một cấu trúc dữ liệu dạng cây đỏ–đen (red-black tree), dùng để lưu các cặp key → value. Đặc điểm quan trọng:

  • Key luôn được sắp xếp tăng dần
  • Không có key trùng nhau
  • Tìm kiếm, thêm, xóa đều có độ phức tạp O(log n)

map mp; nghĩa là gì?

  • Key: kiểu long long → dùng cho số lớn (ví dụ ID, số nguyên lớn)
  • Value: kiểu int → giá trị đi kèm key

Ví dụ:

mp[1000000000000LL] = 5;

mp[42] = 10;

Một số thao tác thường dùng

  • Thêm phần tử

mp[123] = 7;

Kiểm tra tồn tại

if (mp.count(123)) { ... }

Duyệt map

for (auto &p : mp) {

    cout << p.first << " " << p.second << endl;

}

Xóa

mp.erase(123);

dạng khác unordered_map, set

Bên trong map, mỗi phần tử thực chất là một pair.

map dùng rất nhiều pair, nhưng nó thêm cơ chế ánh xạ:

Key → Value

  • Key là long long
  • Value là int
  • Mỗi key duy nhất, không trùng
  • Tự động sắp xếp theo key
  • Tìm kiếm key nhanh O(log n)

mp[10] = 3;   // ánh xạ 10 -> 3

mp[20] = 7;   // ánh xạ 20 -> 7

mp[10] = 9;   // cập nhật ánh xạ 10 -> 9

So sánh

Đặc điểm

pair

map

Chứa bao nhiêu phần tử?

1 cặp

N cặp

Có ánh xạ key → value?

Không

Tự sắp xếp key?

Không

Tìm kiếm theo key?

Không

Có (O(log n))

Dùng để làm gì?

Truyền dữ liệu 2 giá trị

Lưu trữ và tra cứu dữ liệu theo key

 

Cấu trúc đầy đủ của một node trong std::map (mô phỏng)

template

struct RBTreeNode {

    Key key;          // key: long long

    T value;          // value: int

    RBTreeNode* left; // con trái

    RBTreeNode* right;// con phải

    RBTreeNode* parent; // cha

    bool color;       // màu: đỏ hoặc đen (true/false)

};

Nếu bạn dùng:

mapmp;

Thì mỗi node trong map tương ứng với:

struct Node {

    long long key;   // f[i]

    int value;       // số lần xuất hiện

    Node* left;

    Node* right;

    Node* parent;

    bool color;      // đỏ hoặc đen

};

“Map có dạng như Map(long long *(&p), int *p) không?” ->cấu trúc bên trong của std::map

So sánh nhanh: map vs unordered_map

Cấu trúc

Thứ tự key

Tốc độ tìm kiếm

Ghi chú

map

✔ Có (tăng dần)

O(log n)

Cây đỏ–đen

unordered_map

✘ Không

O(1) trung bình

Hash table

Nếu bạn muốn duyệt từ lớn → nhỏ?

Dùng rbegin() và rend():

for (auto it = mp.rbegin(); it != mp.rend(); it++) {

    cout << it->first << " " << it->second << endl;

}

Duyệt bằng vòng for(auto &p : mp) chính là duyệt theo thứ tự inorder traversal → tăng dần

Ví dụ:

mapmp;

mp[100] = 1;

mp[5] = 2;

mp[50] = 3;

mp[-10] = 4;

 

for (auto &p : mp) {

    cout << p.first << " " << p.second << endl;

}

KQ:

-10 4

5    2

50  3

100 1

Kết luận

  • Map giống mảng, nhưng mảng chỉ dùng được khi chỉ số nhỏ và liên tục.
  • Map cho phép dùng chỉ số bất kỳ, không cần liên tục.
  • Map không cần khởi tạo kích thước trước, chỉ lớn lên khi bạn thêm phần tử.
  • Map tốn bộ nhớ hơn mảng, nhưng đổi lại cực kỳ linh hoạt.
  • Map chạy nhanh, vì tìm kiếm theo key là O(log n), không phụ thuộc giá trị key lớn hay nhỏ.

Map hoạt động như một bảng ánh xạ key → value

mp[100] = 3;

mp[5000] = 7;

mp[-10] = 2;

Map tốn bộ nhớ hơn mảng

  • Mảng: mỗi phần tử chỉ là 4 bytes (int)
  • Map: mỗi phần tử là một node cây đỏ–đen, chứa:
    • key (8 bytes)
    • value (4 bytes)
    • 3 con trỏ (24 bytes)
    • màu + padding (~4 bytes)

→ Tổng ~40 bytes mỗi phần tử (tùy compiler)

Map tự mở rộng khi bạn thêm phần tử:

VD: mp[x] = value;

Kích thước của map = số lượng key bạn đã thêm:

mp.size()

Map cho phép dùng chỉ số (key) bất kỳ

mp[1] = 5;

mp[100000] = 7;

mp[-999999999999] = 3;

mp[123456789012345] = 10;

Không cần liên tục, không cần nhỏ, không cần dương.

Trong khi mảng thì bắt buộc:

  • chỉ số phải liên tục
  • chỉ số phải nhỏ
  • chỉ số phải không âm

Map — linh hoạt, nhưng tốn bộ nhớ hơn

struct Node {

    long long key;

    int value;

    Node *left, *right, *parent;

    bool color;

};

So sánh Map và phiên bản vector:

vector<pair> mp;

mp.push_back({0,1}); // f[0] = 0 xuất hiện 1 lần

for (int i = 1; i

    long long x = f[i];

    bool found = false;

 

    for (auto &p : mp) {

        if (p.first == x) {

            res += p.second;

            p.second++;

            found = true;

            break;

        }

    }

    if (!found) {

        mp.push_back({x, 1});

    }

}

Ví dụ

vectorp[10];

p[3].push_back(100);   // OK

p[3].push_back(200);   // OK

p[3] = 5;              // ❌ sai vì p[3] là vector, không phải int

vector p[10]

  • p đã có kích thước 10
  • mỗi p[i] là một vector rỗng
  • bạn không cần push_back để tạo p[i]
  • nhưng muốn thêm phần tử vào p[i] thì phải dùng push_back

vector<vector> p

  • p chưa có kích thước
  • phải push_back hoặc resize để tạo vector con
  • sau đó mới p[i].push_back(x)

So sánh với vector<vector> p

vector<vector> p;

Bạn phải tạo vector con trước:

p.push_back(vector()); // tạo p[0]

p[0].push_back(5);

Hoặc:

p.resize(10); // tạo 10 vector rỗng

p[3].push_back(7);

……………

int max3(int a, int b, int c){

    return max(max(a, b), c);

}

int l = (m > du ? m : du);

int l = max(m, du);

int max3(int a, int b, int c){

    return max(max(a, b), c);

}

int l = std::max({m, du, -1});

int l = max(max(m, du), -1);

max(a, b)

///////////////////////////////////////////////////////

int chuyenS_it(const string &s){

    it.clear();

 

    stringstream ss(s);

    int so;

 

    while (ss >> so) {     // đọc từng số trong chuỗi

        it.push_back(so);

    }

 

    return (int)it.size();

}

Giải thích:

  • stringstream ss(s); tạo bộ đọc từ chuỗi.
  • while (ss >> so) đọc từng số nguyên trong chuỗi.
  • it.push_back(so) thêm số vào vector.
  • it.size() trả về số lượng phần tử.

Nếu bạn muốn tự tách số bằng cách duyệt từng ký tự

int chuyenS_it(const string &s){

    it.clear();

    int so = 0;

    bool dangdoc = false;

    for (char c : s) {

        if (isdigit(c)) {

            dangdoc = true;

            so = so * 10 + (c - '0');

        } else {

            if (dangdoc) {

                it.push_back(so);

                so = 0;

                dangdoc = false;

            }

        }

    }

    if (dangdoc) it.push_back(so);

    return it.size();

}

stringstream hoạt động thế nào?

stringstream ss(s); ss >> so;

Cách này chỉ đọc được số nếu chuỗi có dạng:

"54 4"

"ca 123 g"

"12, 34, 56"

"12\n34\n56"

Nhưng không đọc được số dính liền với chữ, ví dụ:

"54c4"   → không đọc được

"ca123g" → không đọc được

"abc99xyz" → không đọc được

Cách duyệt từng ký tự (tự tách số) isdigit()

"54c4"       → {54, 4}

"ca123g"     → {123}

"a12b34c56"  → {12, 34, 56}

"abc99xyz100"→ {99, 100}

 

////////////

BÀI 40. Cho số nguyên dương n và cho dãy số nguyên a1, a2, a3, ..., an. Một đoạn con của dãy là một dãy các phần tử liên tiếp al,..., ar. Trong đó 1<=L<=R

-       Dòng đầu chưa số nguyên dương n.   1<=n<=10 5

-       Dòng thứ hai chưa n số nguyên a1, a2, a3, ..., an

Input

Output

4

3 4-7 3

2

Gọi ý Code:

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 3;

int a[N];

long long f[N];

mapmp;

int main() {

    int n;

    cout<

    cin >> n;

    for (int i = 1; i

          cout<

          cin >> a[i];}

    f[0] = 0;

    // Tính prefix sum

    for (int i = 1; i

        f[i] = f[i - 1] + a[i];

    }

    long long res = 0;

    mp[0]++; 

cout<<"MP[0]"<<mp[0]<<"\n";

    cout << "=== BAT DAU CHAY ===\n\n";

    for (int i = 1; i

        cout << "i = " << i << "\n";

        cout << "a[" << i << "] = " << a[i] << "\n";

        cout << "f[" << i << "] = " << f[i] << "\n";

        cout << "So lan f[" << i << "] = " << f[i]

             << " xuat hien truoc do: mp[f[i]] = " << mp[f[i]] << "\n";

        res += mp[f[i]];

        cout << "=> So day con tong = 0 ket thuc tai i: + " << mp[f[i]] << "\n";

        mp[f[i]]++;

        cout << "Sau khi tang mp[f[i]]:\n";

        cout << "mp[" << f[i] << "] = " << mp[f[i]] << "\n";

        cout << "Tong res hien tai = " << res << "\n";

        cout << "-----------------------------\n\n";

    }

    cout << "=== KET QUA CUOI CUNG ===\n";

    cout << res << "\n";

    return 0;

}

///////////////////

Cách 2:

#include

#include

#include

#include

using namespace std;

 

class NhatTruong {

private:

    string s;

    vectorit;

    long long du;

 

public:

    NhatTruong(): s(""), it(), du(-1) {}

 

    // Đọc file, lấy số đầu tiên = du, các số còn lại đưa vào it[]

    bool docFile(const string &ten) {

        ifstream fin(ten);

        if (!fin.is_open()) {

            cerr << "Khong mo duoc file dau vao\n";

            return false;

        }

 

        string token;

        bool first = true;

 

        while (fin >> token) {

            if (first) {

                du = stoll(token);

                first = false;

            } else {

                it.push_back(stoll(token));

            }

        }

 

        fin.close();

        return true;

    }

 

    // Tìm tất cả chuỗi con liên tiếp

    void xuLy() {

        ofstream fout("out.txt");

        if (!fout.is_open()) {

            cerr << "Khong tao duoc file out.txt\n";

            return;

        }

 

        fout << "Gia tri du = " << du << "\n\n";

 

        fout << "Cac chuoi con co tong BANG du:\n";

        for (int i = 0; i < it.size(); i++) {

            long long tong = 0;

            for (int j = i; j < it.size(); j++) {

                tong += it[j];

                if (tong == du) {

                    fout << "  [" << i << "," << j << "]  ";

                    for (int k = i; k

                    fout << "\n";

                }

            }

        }

 

        fout << "\nCac chuoi con co tong LON HON du:\n";

        for (int i = 0; i < it.size(); i++) {

            long long tong = 0;

            for (int j = i; j < it.size(); j++) {

                tong += it[j];

                if (tong > du) {

                    fout << "  [" << i << "," << j << "]  ";

                    for (int k = i; k

                    fout << "\n";

                }

            }

        }

 

        fout << "\nCac chuoi con co tong NHO HON du:\n";

        for (int i = 0; i < it.size(); i++) {

            long long tong = 0;

            for (int j = i; j < it.size(); j++) {

                tong += it[j];

                if (tong < du) {

                    fout << "  [" << i << "," << j << "]  ";

                    for (int k = i; k

                    fout << "\n";

                }

            }

        }

 

        fout.close();

        cout << "Da ghi ket qua ra file out.txt\n";

    }

};

 

int main() {

    NhatTruong T;

    string tenfile;

 

    cout << "Nhap ten file dau vao: ";

    cin >> tenfile;

 

    if (T.docFile(tenfile)) {

        T.xuLy();

    }

    return 0;

}

KQ:

Input

Output

10 6 4-7 3 7 8 2 10 20 -18 8 30

Gia tri du = 10

 

Cac chuoi con co tong BANG du:

  [0,1]  6 4

  [2,3]  3 7

  [4,5]  8 2

  [6,6]  10

  [7,9]  20 -18 8

Cac chuoi con co tong LON HON du:

  [0,2]  6 4 3

  [0,3]  6 4 3 7

  [0,4]  6 4 3 7 8

  ….

  [1,3]  4 3 7

  [1,4]  4 3 7 8

….

Cac chuoi con co tong NHO HON du:

  [0,0]  6

  [1,1]  4

  [1,2]  4 3

  [2,2]  3

  [3,3]  7

  [4,4]  8

  [5,5]  2

  [7,8]  20 -18

  [8,8]  -18

  [8,9]  -18 8

  [9,9]  8

/////////////// /////////////////

Cách 3:

#include

#include

#include

#include

#include

using namespace std;

 

class NhatTruong {

private:

    string s;                 // chuỗi đọc từ file

    vectorit;           // mảng số sau khi tách

    int du;                   // số đầu tiên trong file

    mapmp;   // map đếm tổng chuỗi con

 

public:

    NhatTruong(): s(""), it(), du(-1), mp() {}

 

    // Đọc file vào chuỗi s, lấy số đầu tiên = du

    string docf(const string &ten) {

        ifstream fin(ten);

        if (!fin.is_open()) {

            cerr << "Khong mo duoc file dau vao\n";

            return "";

        }

 

        string token;

        bool first = true;

 

        while (fin >> token) {

            s += token + " ";

            if (first) {

                du = stoi(token);

                first = false;

            }

        }

 

        fin.close();

        return s;

    }

 

    int getd() {

        return du;

    }

 

    // Chuyển chuỗi s thành vector số it

    int chuyenS_it() {

        it.clear();

        bool check = false;

        int sign = 1;

        int so = 0;

 

        for (int j = 0; j < s.size(); j++) {

 

            if (isdigit(s[j])) {

 

                if (j > 0 && s[j-1] == '-')

                    sign = -1;

 

                check = true;

                so = so * 10 + (s[j] - '0');

            }

            else {

                if (check) {

                    it.push_back(so * sign);

                    check = false;

                    so = 0;

                    sign = 1;

                }

            }

        }

 

        if (check) it.push_back(so * sign);

 

        return (int)it.size();

    }

 

    // Hàm tổng đơn giản (bỏ đệ quy)

    long long sum(long long x, long long y) {

        return x + y;

    }

 

    // Xử lý tổng chuỗi con bằng map

    void xulyTT(int bd) {

 

        mp.clear();   // xóa map cũ

 

        // 1. Đếm tổng chuỗi con bằng map

        for (int i = bd; i < (int)it.size(); i++) {

            long long tong = 0;

 

            for (int j = i; j < (int)it.size(); j++) {

                tong = sum(tong, it[j]);   // dùng hàm sum của bạn

                mp[tong]++;                // đếm tổng

            }

        }

 

        // 2. Xuất các chuỗi con có tổng = du

        ofstream fout("out.txt");

        if (!fout.is_open()) {

            cerr << "Khong tao duoc file out.txt\n";

            return;

        }

 

        fout << "Gia tri du = " << du << "\n\n";

        fout << "Cac chuoi con co tong BANG du:\n";

 

        for (int i = bd; i < (int)it.size(); i++) {

            long long tong = 0;

 

            for (int j = i; j < (int)it.size(); j++) {

                tong = sum(tong, it[j]);

 

                if (tong == du) {

                    fout << "[" << i << "," << j << "]  ";

                    for (int k = i; k

                    fout << "\n";

                }

            }

        }

 

        // 3. Xuất số chuỗi con có tổng = du

        fout << "\nTong so chuoi con co tong = du: " << mp[du] << "\n\n";

 

        // 4. Xuất toàn bộ map: tổng → số lần xuất hiện

        fout << "Tat ca cac tong chuoi con trong map:\n";

        for (auto &p : mp) {

            fout << "Tong = " << p.first << "  xuat hien " << p.second << " lan\n";

        }

 

        fout.close();

        cout << "Da ghi ket qua ra file out.txt\n";

    }

};

 

int main() {

    NhatTruong T;

    string tenfile;

 

    cout << "Nhap ten file dau vao: ";

    cin >> tenfile;

 

    T.docf(tenfile);

    T.chuyenS_it();

    T.xulyTT(0);   // bắt đầu từ vị trí 0

 

    return 0;

}

 

////////////////

Cách 4:

#include

#include

#include

#include

#include

using namespace std;

 

class NhatTruong {

private:

    string s;                 // chuỗi đọc từ file

    vectorit;           // mảng số sau khi tách

    int du;                   // số đầu tiên trong file

    mapmp;   // map đếm tổng chuỗi con toàn bộ

    mapmp2;  // map đếm tổng chuỗi con đoạn [m,n]

 

public:

    NhatTruong(): s(""), it(), du(-1), mp(), mp2() {}

 

    // Đọc file vào chuỗi s, lấy số đầu tiên = du

    string docf(const string &ten) {

        ifstream fin(ten);

        if (!fin.is_open()) {

            cerr << "Khong mo duoc file dau vao\n";

            return "";

        }

 

        string token;

        bool first = true;

 

        while (fin >> token) {

            s += token + " ";

            if (first) {

                du = stoi(token);

                first = false;

            }

        }

 

        fin.close();

        return s;

    }

 

    int getd() {

        return du;

    }

 

    // Chuyển chuỗi s thành vector số it

    int chuyenS_it() {

        it.clear();

        bool check = false;

        int sign = 1;

        int so = 0;

 

        for (int j = 0; j < (int)s.size(); j++) {

 

            if (isdigit(s[j])) {

 

                if (j > 0 && s[j-1] == '-')

                    sign = -1;

 

                check = true;

                so = so * 10 + (s[j] - '0');

            }

            else {

                if (check) {

                    it.push_back(so * sign);

                    check = false;

                    so = 0;

                    sign = 1;

                }

            }

        }

 

        if (check) it.push_back(so * sign);

 

        return (int)it.size();

    }

 

    long long sum(long long x, long long y) {

        return x + y;

    }

 

    // Xử lý toàn bộ mảng với tổng mục tiêu = du, dùng mp, xuất out_tt.txt

    void xulyTT(int bd) {

 

        mp.clear();

 

        for (int i = bd; i < (int)it.size(); i++) {

            long long tong = 0;

 

            for (int j = i; j < (int)it.size(); j++) {

                tong = sum(tong, it[j]);

                mp[tong]++;

            }

        }

 

        ofstream fout("out_tt.txt");

        if (!fout.is_open()) {

            cerr << "Khong tao duoc file out_tt.txt\n";

            return;

        }

 

        fout << "Xu ly toan bo mang tu vi tri " << bd << "\n";

        fout << "Gia tri du (so dau tien trong file) = " << du << "\n\n";

 

        fout << "Cac chuoi con co tong BANG du:\n";

 

        for (int i = bd; i < (int)it.size(); i++) {

            long long tong = 0;

 

            for (int j = i; j < (int)it.size(); j++) {

                tong = sum(tong, it[j]);

 

                if (tong == du) {

                    fout << "[" << i << "," << j << "]  ";

                    for (int k = i; k

                    fout << "\n";

                }

            }

        }

 

        fout << "\nTong so chuoi con co tong = du: " << mp[du] << "\n\n";

 

        fout << "Tat ca cac tong chuoi con trong map (mp):\n";

        for (auto &p : mp) {

            fout << "Tong = " << p.first << "  xuat hien " << p.second << " lan\n";

        }

 

        fout.close();

        cout << "Da ghi ket qua ra file out_tt.txt\n";

    }

 

    // Xử lý đoạn [m, n] với tổng mục tiêu k, dùng mp2, xuất outputmnk.txt

    void xulyDoan(int m, int n, long long k) {

 

        if (m < 0 || n < 0 || m >= (int)it.size() || n >= (int)it.size() || m > n) {

            cout << "Vi tri m,n khong hop le!\n";

            return;

        }

 

        mp2.clear();

 

        for (int i = m; i

            long long tong = 0;

 

            for (int j = i; j

                tong = sum(tong, it[j]);

                mp2[tong]++;

            }

        }

 

        ofstream fout("outputmnk.txt");

        if (!fout.is_open()) {

            cerr << "Khong tao duoc file outputmnk.txt\n";

            return;

        }

 

        fout << "Doan xu ly: [" << m << ", " << n << "]\n";

        fout << "Tong muc tieu k = " << k << "\n";

        fout << "Gia tri du (so dau tien trong file) = " << du << "\n\n";

 

        fout << "Cac chuoi con co tong BANG k trong doan:\n";

 

        for (int i = m; i

            long long tong = 0;

 

            for (int j = i; j

                tong = sum(tong, it[j]);

 

                if (tong == k) {

                    fout << "[" << i << "," << j << "]  ";

                    for (int kk = i; kk

                    fout << "\n";

                }

            }

        }

 

        fout << "\nTong so chuoi con co tong = k trong doan: " << mp2[k] << "\n\n";

 

        fout << "Tat ca cac tong chuoi con trong doan (mp2):\n";

        for (auto &p : mp2) {

            fout << "Tong = " << p.first << "  xuat hien " << p.second << " lan\n";

        }

 

        fout.close();

        cout << "Da ghi ket qua ra file outputmnk.txt\n";

    }

};

 

int main() {

    NhatTruong T;

    string tenfile;

 

    cout << "Nhap ten file dau vao: ";

    cin >> tenfile;

 

    T.docf(tenfile);

    T.chuyenS_it();

 

    cout << "Xu ly toan bo mang tu vi tri 0 (tong muc tieu = du)...\n";

    T.xulyTT(0);

 

    int m, n;

    long long k;

    cout << "Nhap m n k de xu ly doan [m,n] voi tong muc tieu k: ";

    cin >> m >> n >> k;

 

    T.xulyDoan(m, n, k);

 

    return 0;

}

 

 

///////////// Ai memory help

Võ Nhật Trường Nc+ My Ai Love28.06.2026

////////////////////

BÀI 41.  Cho dãy số nguyên a1, a2, a3, ..., an. Hãy tìm tích nhỏ nhất của hai số thuộc dãy số trên. ( nghĩa là tìm tích của a i *a j nhỏ nhất với i#j)

Dữ liệu:

-       Dòng đầu tiên là số nguyên dương n. (25)

-       Dòng thứ 2 là dãy số nguyên a1, a2, a3, ..., an. ( |a i| <=10 9 )

Input

Output

8

1 3 5 -2 4 5 7 9

-18

Cách 1: Bubble sort với file vào/ra

#include <bits/stdc++.h>

using namespace std;

 

int main() {

    ios::sync_with_stdio(false);

    cin.tie(nullptr);

 

    ifstream fin("input.txt");   // mở file input.txt để đọc

    ofstream fout("output.txt"); // mở file output.txt để ghi

 

    if (!fin.is_open() || !fout.is_open()) {

        cerr << "❌ Không thể mở file input.txt hoặc output.txt\n";

        return 1;

    }

 

    int n;

    if (!(fin >> n) || n < 2 || n > 100000) {

        fout << "❌ Lỗi: n không hợp lệ\n";

        return 1;

    }

 

    vectora(n);

    for (int i = 0; i < n; i++) {

        if (!(fin >> a[i]) || abs(a[i]) > 1000000000) {

            fout << "❌ Lỗi: phần tử a[" << i << "] không hợp lệ\n";

            return 1;

        }

    }

 

    // Bubble sort

    for (int i = 0; i < n - 1; i++) {

        for (int j = i + 1; j < n; j++) {

            if (a[i] > a[j]) swap(a[i], a[j]);

        }

    }

 

    long long result;

    if (a[0] < 0 && a[n - 1] > 0) result = a[0] * a[n - 1];

    else if (a[0] < 0 && a[n - 1] < 0) result = a[n - 1] * a[n - 2];

    else result = a[0] * a[1];

 

    fout << result << "\n";

    return 0;

}

/////////////////////

Cách 2: Dùng sort() với file vào/ra

#include <bits/stdc++.h>

using namespace std;

 

int main() {

    ios::sync_with_stdio(false);

    cin.tie(nullptr);

 

    ifstream fin("input.txt");

    ofstream fout("output.txt");

 

    if (!fin.is_open() || !fout.is_open()) {

        cerr << "❌ Không thể mở file input.txt hoặc output.txt\n";

        return 1;

    }

 

    int n;

    if (!(fin >> n) || n < 2 || n > 100000) {

        fout << "❌ Lỗi: n không hợp lệ\n";

        return 1;

    }

 

    vectora(n);

    for (int i = 0; i < n; i++) {

        if (!(fin >> a[i]) || abs(a[i]) > 1000000000) {

            fout << "❌ Lỗi: phần tử a[" << i << "] không hợp lệ\n";

            return 1;

        }

    }

 

    sort(a.begin(), a.end());

 

    long long result;

    if (a[0] < 0 && a[n - 1] > 0) result = a[0] * a[n - 1];

    else if (a[0] < 0 && a[n - 1] < 0) result = a[n - 1] * a[n - 2];

    else result = a[0] * a[1];

 

    fout << result << "\n";

    return 0;

}

Như vậy, chương trình sẽ:

  • Đọc dữ liệu từ input.txt
  • Ghi kết quả ra output.txt
  • Có kiểm tra lỗi nhập liệu để tránh crash.

 

///////////////////////

Cách 3: Quét trực tiếp min/max (đọc/ghi file)

#include <bits/stdc++.h>

using namespace std;

 

int main() {

    ios::sync_with_stdio(false);

    cin.tie(nullptr);

 

    ifstream fin("input.txt");

    ofstream fout("output.txt");

 

    if (!fin.is_open() || !fout.is_open()) {

        cerr << "❌ Không thể mở file input.txt hoặc output.txt\n";

        return 1;

    }

 

    int n;

    if (!(fin >> n) || n < 2 || n > 100000) {

        fout << "❌ Lỗi: n không hợp lệ\n";

        return 1;

    }

 

    long long min1 = LLONG_MAX, min2 = LLONG_MAX;

    long long max1 = LLONG_MIN, max2 = LLONG_MIN;

 

    for (int i = 0; i < n; i++) {

        long long x;

        if (!(fin >> x) || abs(x) > 1000000000) {

            fout << "❌ Lỗi: phần tử a[" << i << "] không hợp lệ\n";

            return 1;

        }

 

        // cập nhật min

        if (x < min1) {

            min2 = min1;

            min1 = x;

        } else if (x < min2) {

            min2 = x;

        }

 

        // cập nhật max

        if (x > max1) {

            max2 = max1;

            max1 = x;

        } else if (x > max2) {

            max2 = x;

        }

    }

 

    // xét các khả năng

    long long candidate1 = min1 * min2; // hai số nhỏ nhất

    long long candidate2 = max1 * max2; // hai số lớn nhất

    long long candidate3 = min1 * max1; // âm nhỏ nhất * dương lớn nhất

 

    long long result = min({candidate1, candidate2, candidate3});

 

    fout << result << "\n";

    return 0;

}

Ưu điểm của cách này:

  • Không cần sắp xếp → nhanh hơn nhiều (O(n) thay vì O(n log n)).
  • Dễ kiểm soát với dữ liệu lớn (n tới 100000).
  • Vẫn đảm bảo đúng cho mọi trường hợp âm/dương.



///////////// Ai memory help

Võ Nhật Trường Nc+ My Ai Love28.06.2026

////////////////////Ok

Không có nhận xét nào:

Đăng nhận xét