[0]zero-index clytie0x/zero-index

15.6 แบบฝึกหัด

เขียนแต่ละข้อเป็นไฟล์ใหม่ใน Code::Blocks รันแล้วเทียบกับผลลัพธ์ที่ต้องได้ให้ตรงทุกตัวอักษร รวมถึงช่องว่างและการขึ้นบรรทัด ติดจริงๆ ค่อยเปิดคำใบ้ และเปิดเฉลยหลังทำเสร็จแล้วเท่านั้น

ข้อ 1 เรียงวันที่ใหม่

ระดับง่าย เวลาไม่เกิน 1 วินาที

ใบสมัครค่ายให้น้องกรอกวันเกิดแบบ วัน/เดือน/ปี เช่น 05/03/2010 แต่ระบบของค่ายเรียงข้อมูลตามวันที่ได้ก็ต่อเมื่อเขียนแบบ ปี-เดือน-วัน คือ 2010-03-05 ให้แปลงวันเกิดทุกรายการให้เป็นรูปแบบใหม่ โดยเลข 0 ที่อยู่ข้างหน้าต้องอยู่ครบเหมือนเดิม

ข้อมูลเข้า

บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)

อีก N บรรทัด บรรทัดละหนึ่งวันที่ในรูปแบบ DD/MM/YYYY ยาว 10 ตัวพอดี วันและเดือนเป็นเลขสองหลักเสมอ ปีเป็นเลขสี่หลักเสมอ ทุกวันที่เป็นวันที่ที่มีอยู่จริง

ข้อมูลออก

N บรรทัด บรรทัดที่ i คือวันที่ของบรรทัดที่ i ในรูปแบบ YYYY-MM-DD

3
05/03/2010
28/11/2009
14/02/2011
2010-03-05
2009-11-28
2011-02-14
ดูคำใบ้

อ่านทั้งวันที่เป็น string ด้วย cin >> แล้วตัดสามส่วนด้วย substr แบบตัวอย่างวันที่ในหน้า 15.4 วันอยู่ช่อง 0 ยาว 2 ตัว เดือนอยู่ช่อง 3 ปีอยู่ช่อง 6 ยาว 4 ตัว ถ้าอ่านเป็นตัวเลขด้วย int เลข 0 ข้างหน้าจะหายไป

ดูเฉลย
#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        string date;
        cin >> date;
        cout << date.substr(6, 4) << '-' << date.substr(3, 2) << '-' << date.substr(0, 2) << '\n';
    }
    return 0;
}

ข้อ 2 จัดรูปแบบชื่อบนป้าย

ระดับง่าย เวลาไม่เกิน 1 วินาที

ค่ายจะพิมพ์ป้ายชื่อให้นักเรียนทุกคน แต่ตอนกรอกใบสมัคร แต่ละคนพิมพ์ชื่อมาไม่เหมือนกัน บางคนพิมพ์ตัวพิมพ์ใหญ่ทั้งหมด บางคนพิมพ์ตัวพิมพ์เล็กทั้งหมด บางคนกดสลับไปมา ป้ายชื่อต้องเป็นรูปแบบเดียวกันทุกใบ คือชื่อที่ขึ้นต้นด้วยตัวพิมพ์ใหญ่และที่เหลือเป็นตัวพิมพ์เล็ก ตามด้วยช่องว่างหนึ่งช่อง ตามด้วยอักษรตัวแรกของนามสกุลเป็นตัวพิมพ์ใหญ่และจุด เช่น sOMCHAI jaidee ต้องเป็น Somchai J.

ข้อมูลเข้า

บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)

อีก N บรรทัด บรรทัดละหนึ่งคน มีชื่อและนามสกุลคั่นด้วยช่องว่าง ทั้งสองเป็นตัวอักษรภาษาอังกฤษล้วน ตัวพิมพ์ใหญ่หรือเล็กก็ได้ ยาวคำละ 1 ถึง 20 ตัว

ข้อมูลออก

N บรรทัด บรรทัดที่ i คือป้ายชื่อของคนที่ i

3
sOMCHAI jaidee
MALEE Srisuk
ploy WONG
Somchai J.
Malee S.
Ploy W.
ดูคำใบ้

อ่านชื่อกับนามสกุลเป็น string สองตัว เปลี่ยนชื่อทั้งคำเป็นตัวพิมพ์เล็กก่อนด้วย for (char &c : first) กับ tolower แล้วค่อยเปลี่ยน first[0] เป็นตัวพิมพ์ใหญ่ ส่วนนามสกุลใช้แค่ toupper(last[0]) ระวังว่า toupper คืนค่าเป็น int ถ้าส่งให้ cout ตรงๆ จะได้ตัวเลข ต้องเก็บใส่ตัวแปร char ก่อน หรือเขียน (char)toupper(last[0])

ดูเฉลย
#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        string first, last;
        cin >> first >> last;
        for (char &c : first) {
            c = tolower(c);
        }
        first[0] = toupper(first[0]);
        char initial = toupper(last[0]);
        cout << first << ' ' << initial << ".\n";
    }
    return 0;
}

ข้อ 3 คนที่ได้คะแนนสูงสุด

ระดับง่าย เวลาไม่เกิน 1 วินาที

หลังสอบย่อยวิชาคอมพิวเตอร์ ครูประจำวิชามีรายชื่อนักเรียน N คนพร้อมคะแนน ครูอยากรู้สองอย่าง คือคะแนนเฉลี่ยของห้อง และชื่อของคนที่ได้คะแนนสูงสุด ถ้ามีหลายคนได้คะแนนสูงสุดเท่ากัน ให้ตอบคนที่อยู่ก่อนในรายชื่อ

ข้อนี้คล้ายข้อใครได้รางวัลในบทที่ 11 และตั้งใจให้ฝึกย้ายโค้ดภาษา C มาเป็น C++ ให้เก็บชื่อด้วย string อ่านเขียนด้วย cin cout แทน char อาเรย์ strcpy และ printf

ข้อมูลเข้า

บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)

อีก N บรรทัด บรรทัดละหนึ่งคน มีชื่อและคะแนนคั่นด้วยช่องว่าง ชื่อเป็นตัวอักษรภาษาอังกฤษ ยาว 1 ถึง 20 ตัว ไม่มีช่องว่าง คะแนนเป็นจำนวนเต็มตั้งแต่ 0 ถึง 100

ข้อมูลออก

บรรทัดแรกคือคะแนนเฉลี่ย เป็นทศนิยม 2 ตำแหน่ง บรรทัดที่สองคือชื่อของคนที่ได้คะแนนสูงสุด

3
Malee 72
Somchai 85
Ploy 64
73.67
Somchai
6
Anan 90
Nok 95
Kitti 95
Wan 88
Pim 70
Ton 81
86.50
Nok
ดูคำใบ้

เก็บคะแนนสูงสุดที่เจอไว้ใน int และชื่อของคนนั้นไว้ใน string เจอคนที่คะแนนมากกว่าค่าเดิมเมื่อไรค่อยเปลี่ยน ใช้ = คัดลอกชื่อได้เลย ไม่ต้องใช้ strcpy ถ้าใช้ >= จะได้คนสุดท้ายที่ได้คะแนนเท่ากัน ค่าเฉลี่ยต้องหารแบบทศนิยม แล้วพิมพ์ด้วย fixed กับ setprecision(2) ตามหน้า 15.2

ดูเฉลย
#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    int total = 0;
    int best_score = -1;
    string best_name;
    for (int i = 0; i < n; i++) {
        string name;
        int score;
        cin >> name >> score;
        total += score;
        if (score > best_score) {
            best_score = score;
            best_name = name;
        }
    }
    cout << fixed << setprecision(2);
    cout << (double)total / n << '\n';
    cout << best_name << '\n';
    return 0;
}

ข้อ 4 ตรวจรหัสผ่าน

ระดับง่าย เวลาไม่เกิน 1 วินาที

เว็บส่งงานของโรงเรียนให้นักเรียนตั้งรหัสผ่านใหม่ รหัสผ่านต้องผ่านกฎสี่ข้อนี้ ระบบจะตรวจตามลำดับ และบอกเฉพาะข้อแรกที่ไม่ผ่าน

  1. ยาวอย่างน้อย 8 ตัว ถ้าไม่ผ่านให้ตอบ TOO SHORT
  2. มีตัวพิมพ์ใหญ่ A ถึง Z อย่างน้อยหนึ่งตัว ถ้าไม่ผ่านให้ตอบ NO UPPERCASE
  3. มีตัวพิมพ์เล็ก a ถึง z อย่างน้อยหนึ่งตัว ถ้าไม่ผ่านให้ตอบ NO LOWERCASE
  4. มีตัวเลข 0 ถึง 9 อย่างน้อยหนึ่งตัว ถ้าไม่ผ่านให้ตอบ NO DIGIT

ถ้าผ่านครบทั้งสี่ข้อให้ตอบ OK ให้ตรวจรหัสผ่านที่นักเรียนส่งมาทั้งหมด

ข้อมูลเข้า

บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000)

อีก N บรรทัด บรรทัดละหนึ่งรหัสผ่าน ยาว 1 ถึง 50 ตัว ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข และเครื่องหมาย เช่น ! @ # $ % _ - . ไม่มีช่องว่าง

ข้อมูลออก

N บรรทัด บรรทัดที่ i คือผลการตรวจรหัสผ่านที่ i

5
abc
school2026
School2026
SCHOOL2026
SchoolDays
TOO SHORT
NO UPPERCASE
OK
NO LOWERCASE
NO DIGIT
ดูคำใบ้

ใช้ตัวแปร bool สามตัว เช่น has_upper has_lower has_digit ตั้งเป็น false ก่อน แล้วเดินทีละตัวด้วย for (char c : password) เจอตัวแบบไหนก็ตั้งตัวแปรนั้นเป็น true จากนั้นใช้ if else if ไล่ตามลำดับกฎ ความยาวต้องตรวจก่อนข้ออื่นเสมอ แม้รหัสสั้นจะไม่มีตัวพิมพ์ใหญ่ด้วยก็ตอบแค่ TOO SHORT

ดูเฉลย
#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        string password;
        cin >> password;
        bool has_upper = false, has_lower = false, has_digit = false;
        for (char c : password) {
            if (c >= 'A' && c <= 'Z') {
                has_upper = true;
            } else if (c >= 'a' && c <= 'z') {
                has_lower = true;
            } else if (c >= '0' && c <= '9') {
                has_digit = true;
            }
        }
        if ((int)password.size() < 8) {
            cout << "TOO SHORT\n";
        } else if (!has_upper) {
            cout << "NO UPPERCASE\n";
        } else if (!has_lower) {
            cout << "NO LOWERCASE\n";
        } else if (!has_digit) {
            cout << "NO DIGIT\n";
        } else {
            cout << "OK\n";
        }
    }
    return 0;
}

ข้อ 5 อีเมลโรงเรียน

ระดับกลาง เวลาไม่เกิน 1 วินาที

ครูเปิดฟอร์มให้นักเรียนส่งอีเมลมาเพื่อเพิ่มเข้ากลุ่มของห้อง แต่กลุ่มนี้รับเฉพาะอีเมลของโรงเรียน ซึ่งลงท้ายด้วยโดเมน D เช่น school.ac.th นักเรียนบางคนพิมพ์อีเมลส่วนตัวมา บางคนพิมพ์ผิด ครูอยากได้รายชื่อผู้ใช้ของอีเมลโรงเรียนที่ถูกต้องเท่านั้น

ข้อความหนึ่งรายการถือเป็นอีเมลโรงเรียนที่ถูกต้องเมื่อครบทุกข้อต่อไปนี้

  • มีเครื่องหมาย @ หนึ่งตัวพอดี
  • ส่วนหน้า @ ซึ่งเรียกว่าชื่อผู้ใช้ ยาวอย่างน้อยหนึ่งตัว
  • ส่วนหลัง @ เหมือนกับ D ทุกตัวอักษร ตัวพิมพ์ใหญ่กับตัวพิมพ์เล็กถือว่าต่างกัน

เช่น ถ้า D คือ school.ac.th แล้ว malee@school.ac.th ถูกต้อง แต่ malee@myschool.ac.th malee@school.ac.th.com และ malee@School.ac.th ไม่ถูกต้อง

ข้อมูลเข้า

บรรทัดแรกคือโดเมน D ยาว 1 ถึง 30 ตัว ไม่มีเครื่องหมาย @

บรรทัดที่สองมีจำนวนเต็ม N (1 ≤ N ≤ 1000)

อีก N บรรทัด บรรทัดละหนึ่งรายการ ยาว 1 ถึง 60 ตัว ประกอบด้วยตัวอักษรภาษาอังกฤษ ตัวเลข และเครื่องหมาย . _ - @ ไม่มีช่องว่าง

ข้อมูลออก

ชื่อผู้ใช้ของทุกรายการที่เป็นอีเมลโรงเรียนที่ถูกต้อง บรรทัดละหนึ่งชื่อ เรียงตามลำดับในข้อมูลเข้า แล้วบรรทัดสุดท้ายคือจำนวนรายการที่ถูกต้อง ถ้าไม่มีเลยให้พิมพ์แค่ 0

school.ac.th
5
malee@school.ac.th
somchai@gmail.com
ploy.w@school.ac.th
nok@myschool.ac.th
anan
malee
ploy.w
2
school.ac.th
2
boy@School.ac.th
kitti@school.ac.th.com
0
ดูคำใบ้

หาตำแหน่งของ @ ด้วย find เก็บใน size_t แล้วเทียบกับ string::npos ตามหน้า 15.4 ถ้าเจอ ให้หาต่อด้วย find('@', at + 1) ว่ามีตัวที่สองไหม จากนั้นตัดสองส่วนด้วย substr แล้วเทียบส่วนหลังกับ D ด้วย == ทั้งคำ อย่าใช้ find(D) หาว่า D อยู่ในข้อความไหม เพราะ @myschool.ac.th ก็มี school.ac.th อยู่ข้างใน

ดูเฉลย
#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    string domain;
    int n;
    cin >> domain >> n;
    int valid = 0;
    for (int i = 0; i < n; i++) {
        string email;
        cin >> email;
        size_t at = email.find('@');
        if (at == string::npos || at == 0) {
            continue;
        }
        if (email.find('@', at + 1) != string::npos) {
            continue;
        }
        if (email.substr(at + 1) == domain) {
            cout << email.substr(0, at) << '\n';
            valid++;
        }
    }
    cout << valid << '\n';
    return 0;
}

ข้อ 6 ยอดเงินสะสม

ระดับกลาง เวลาไม่เกิน 1 วินาที

ร้านค้าสหกรณ์ของโรงเรียนจดยอดเงินเข้าออกทุกรายการตลอดปีการศึกษา รายการที่ i เป็นจำนวนเต็ม ai บาท ถ้าเป็นบวกคือเงินเข้า ถ้าเป็นลบคือเงินออก ฝ่ายบัญชีอยากเห็นยอดเงินสะสมหลังแต่ละรายการ คือหลังรายการที่ k ยอดสะสมเท่ากับ a1 + a2 + ... + ak และอยากรู้ด้วยว่าจนถึงรายการนั้น ยอดสะสมเคยต่ำที่สุดเท่าไร เพื่อดูว่าร้านเคยติดลบหนักแค่ไหน

ข้อนี้ข้อมูลเข้ามีได้ถึงหนึ่งล้านรายการ และต้องพิมพ์ออกหนึ่งล้านบรรทัด ภายในเวลา 1 วินาที

ข้อมูลเข้า

บรรทัดแรกมีจำนวนเต็ม N (1 ≤ N ≤ 1000000)

บรรทัดที่สองมีจำนวนเต็ม a1 a2 ... aN คั่นด้วยช่องว่าง (-1000000000 ≤ ai ≤ 1000000000)

ข้อมูลออก

N บรรทัด บรรทัดที่ k มีจำนวนเต็มสองตัวคั่นด้วยช่องว่าง ตัวแรกคือยอดเงินสะสมหลังรายการที่ k ตัวที่สองคือยอดสะสมที่ต่ำที่สุดในบรรดายอดสะสมหลังรายการที่ 1 ถึงรายการที่ k

5
500 -200 1000 -1300 50
500 500
300 300
1300 300
0 0
50 0
ดูคำใบ้

บวกสะสมไปแล้วพิมพ์ทุกรอบ ไม่ต้องเก็บอาเรย์ เก็บยอดที่ต่ำที่สุดไว้อีกตัวแปรหนึ่ง แล้วเทียบกับยอดใหม่ทุกรอบ ค่าเริ่มต้นของมันต้องเป็นยอดหลังรายการแรก ถ้าเริ่มที่ 0 ร้านที่ยอดเป็นบวกตลอดจะได้ 0 ซึ่งไม่เคยเป็นยอดสะสมเลย ยอดสะสมได้ถึง ±106 × 109 = ±1015 ทั้งสองตัวต้องเป็น long long ส่วนที่ยากคือเวลา หน้า 15.3 วัดไว้ว่า cin cout แบบปกติกับข้อมูลขนาดนี้ใช้กว่า 3 วินาที ต้องใส่ ios::sync_with_stdio(false); กับ cin.tie(nullptr); ไว้ต้น main และขึ้นบรรทัดด้วย '\n' ไม่ใช่ endl

ดูเฉลย
#include <bits/stdc++.h>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    long long total = 0;
    long long lowest = 0;
    for (int i = 0; i < n; i++) {
        int amount;
        cin >> amount;
        total += amount;
        if (i == 0 || total < lowest) {
            lowest = total;
        }
        cout << total << ' ' << lowest << '\n';
    }
    return 0;
}

ข้อ 7 กันสปอยล์

ระดับยาก เวลาไม่เกิน 1 วินาที

ชมรมภาพยนตร์มีกลุ่มแชตที่ห้ามสปอยล์ ประธานชมรมรวบรวมคำต้องห้ามไว้ K คำ เช่นชื่อตัวร้ายหรือชื่อฉากสำคัญ ก่อนข้อความจะขึ้นในกลุ่ม ระบบจะเปลี่ยนทุกคำที่ตรงกับคำต้องห้ามเป็นเครื่องหมาย * ที่ยาวเท่าคำนั้น

คำในข้อความคือกลุ่มตัวอักษรที่ติดกันโดยไม่มีช่องว่างคั่น ระบบเปลี่ยนเฉพาะคำที่ตรงกับคำต้องห้ามทั้งคำ เท่านั้น ถ้าคำต้องห้ามเป็นแค่ส่วนหนึ่งของคำที่ยาวกว่าจะไม่ถูกเปลี่ยน เช่น ถ้า cat เป็นคำต้องห้าม คำว่า catch ยังอยู่เหมือนเดิม ช่องว่างในข้อความต้องอยู่ครบทุกช่องเหมือนเดิม

ข้อมูลเข้า

บรรทัดแรกมีจำนวนเต็ม K (1 ≤ K ≤ 100)

บรรทัดที่สองมีคำต้องห้าม K คำ คั่นด้วยช่องว่าง แต่ละคำเป็นตัวพิมพ์เล็กภาษาอังกฤษ ยาว 1 ถึง 20 ตัว อาจมีคำซ้ำกัน

บรรทัดที่สามคือข้อความ ยาว 1 ถึง 100000 ตัว ประกอบด้วยตัวพิมพ์เล็กภาษาอังกฤษและช่องว่างเท่านั้น มีตัวอักษรอย่างน้อยหนึ่งตัว ระหว่างคำและหน้าข้อความอาจมีช่องว่างหลายช่อง แต่ท้ายข้อความไม่มีช่องว่าง

ข้อมูลออก

ข้อความหลังเปลี่ยนคำต้องห้ามแล้ว หนึ่งบรรทัด

2
vader father
darth vader is luke father
darth ***** is luke ******
1
cat
the cat  can catch a cat
the ***  can catch a ***
ดูคำใบ้

ข้อความมีช่องว่าง ต้องรับด้วย getline และเพราะบรรทัดก่อนหน้าอ่านด้วย cin >> ต้องมี cin.ignore(1000000, '\n'); ก่อน ไม่อย่างนั้นจะได้ข้อความว่าง เก็บคำต้องห้ามไว้ในอาเรย์ string banned[100] แล้วเดินในข้อความด้วย i เจอตัวอักษรที่ช่อง i ให้เดินต่อด้วย j จนสุดคำ ตัดคำออกมาด้วย substr(i, j - i) ถ้าเท่ากับคำต้องห้ามสักคำ ให้เปลี่ยนช่อง i ถึง j - 1 เป็น '*' แล้วไปต่อที่ j อย่าใช้ find หาคำต้องห้ามในข้อความตรงๆ เพราะจะไปเจอข้างในคำที่ยาวกว่า

ดูเฉลย
#include <bits/stdc++.h>
using namespace std;

string banned[100];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int k;
    cin >> k;
    for (int i = 0; i < k; i++) {
        cin >> banned[i];
    }
    cin.ignore(1000000, '\n');
    string text;
    getline(cin, text);
    int n = text.size();
    int i = 0;
    while (i < n) {
        if (text[i] == ' ') {
            i++;
            continue;
        }
        int j = i;
        while (j < n && text[j] != ' ') {
            j++;
        }
        string word = text.substr(i, j - i);
        bool hide = false;
        for (int b = 0; b < k; b++) {
            if (word == banned[b]) {
                hide = true;
            }
        }
        if (hide) {
            for (int p = i; p < j; p++) {
                text[p] = '*';
            }
        }
        i = j;
    }
    cout << text << '\n';
    return 0;
}

ข้อ 8 เลือกตั้งประธานนักเรียน

ระดับยาก เวลาไม่เกิน 1 วินาที

โรงเรียนเลือกตั้งประธานนักเรียน มีผู้สมัคร K คน นักเรียนทุกคนเขียนชื่อผู้สมัครที่ตัวเองเลือกลงบัตรหนึ่งใบ บัตรถูกพิมพ์เข้าระบบตามที่เขียนมา บางใบเขียนตัวพิมพ์ใหญ่ บางใบตัวพิมพ์เล็ก บางใบปนกัน ซึ่งถือเป็นชื่อเดียวกันหมด เช่น Malee MALEE และ malee คือคะแนนของ malee ส่วนบัตรที่ชื่อไม่ตรงกับผู้สมัครคนไหนเลย แม้จะสะกดผิดไปตัวเดียว ถือเป็นบัตรเสีย

ให้นับคะแนนของผู้สมัครแต่ละคน นับบัตรเสีย และประกาศผู้ชนะ ผู้ชนะคือคนที่ได้คะแนนมากที่สุดเพียงคนเดียว ถ้ามีหลายคนได้คะแนนมากที่สุดเท่ากัน ให้ประกาศว่าเสมอ

ข้อมูลเข้า

บรรทัดแรกมีจำนวนเต็ม K (1 ≤ K ≤ 10)

บรรทัดที่สองมีชื่อผู้สมัคร K ชื่อ คั่นด้วยช่องว่าง แต่ละชื่อเป็นตัวพิมพ์เล็กภาษาอังกฤษ ยาว 1 ถึง 15 ตัว และไม่ซ้ำกัน

บรรทัดที่สามมีจำนวนเต็ม N (1 ≤ N ≤ 1000000) คือจำนวนบัตร

อีก N บรรทัด บรรทัดละหนึ่งบัตร เป็นตัวอักษรภาษาอังกฤษล้วน ตัวพิมพ์ใหญ่หรือเล็กก็ได้ ยาว 1 ถึง 15 ตัว

ข้อมูลออก

K บรรทัดแรก บรรทัดที่ i มีชื่อผู้สมัครคนที่ i ตามลำดับในข้อมูลเข้า ตามด้วยช่องว่างและคะแนนของคนนั้น

บรรทัดถัดมาคือคำว่า invalid ตามด้วยช่องว่างและจำนวนบัตรเสีย

บรรทัดสุดท้ายคือชื่อผู้ชนะ ถ้าคะแนนสูงสุดเสมอกันตั้งแต่สองคนขึ้นไป ให้พิมพ์ TIE

3
malee somchai ploy
7
Malee
SOMCHAI
malee
plooy
Ploy
mALEE
somchai
malee 3
somchai 2
ploy 1
invalid 1
malee
2
anan nok
5
Anan
NOK
anann
nok
ANAN
anan 2
nok 2
invalid 1
TIE
ดูคำใบ้

เก็บชื่อผู้สมัครในอาเรย์ string name[10] และคะแนนใน int votes[10] เขียนฟังก์ชัน void make_lower(string &word) ที่รับ reference แล้วเปลี่ยนทุกตัวเป็นตัวพิมพ์เล็กด้วย for (char &c : word) พออ่านบัตรมาแล้วเรียกฟังก์ชันนี้ก่อน แล้วค่อยเทียบกับชื่อผู้สมัครทีละคนด้วย == ไม่ตรงใครเลยคือบัตรเสีย ตอนหาผู้ชนะ ให้หาคะแนนสูงสุดก่อน แล้วนับว่ามีกี่คนที่ได้คะแนนเท่านั้น บัตรมีได้ถึงล้านใบ อย่าลืมสองบรรทัดจากหน้า 15.3

ดูเฉลย
#include <bits/stdc++.h>
using namespace std;

string name[10];
int votes[10];

void make_lower(string &word)
{
    for (char &c : word) {
        c = tolower(c);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int k;
    cin >> k;
    for (int i = 0; i < k; i++) {
        cin >> name[i];
    }
    int n;
    cin >> n;
    int invalid = 0;
    for (int b = 0; b < n; b++) {
        string ballot;
        cin >> ballot;
        make_lower(ballot);
        bool counted = false;
        for (int i = 0; i < k; i++) {
            if (ballot == name[i]) {
                votes[i]++;
                counted = true;
            }
        }
        if (!counted) {
            invalid++;
        }
    }
    int best = 0;
    for (int i = 0; i < k; i++) {
        cout << name[i] << ' ' << votes[i] << '\n';
        if (votes[i] > votes[best]) {
            best = i;
        }
    }
    cout << "invalid " << invalid << '\n';
    int winners = 0;
    for (int i = 0; i < k; i++) {
        if (votes[i] == votes[best]) {
            winners++;
        }
    }
    if (winners == 1) {
        cout << name[best] << '\n';
    } else {
        cout << "TIE\n";
    }
    return 0;
}