C++ ทำงานได้เร็วมากเมื่อเทียบกับ Python หรือ Java ซึ่งสำคัญมากในโจทย์ที่มีข้อจำกัดเวลา
มีไลบรารีที่รวบรวมโครงสร้างข้อมูลและอัลกอริทึมที่มีประสิทธิภาพไว้พร้อมใช้งาน
สถิติจาก Google Code Jam พบว่าผู้เข้าแข่งขันระดับท็อป 79% เลือกใช้ C++
#include <bits/stdc++.h> // รวมทุกไลบรารีมาตรฐาน
using namespace std; // เรียกใช้ std โดยตรง
int main() {
ios::sync_with_stdio(0); cin.tie(0); // Fast I/O
// โค้ดสำหรับแก้ปัญหาเขียนตรงนี้
return 0;
}
int a, b; string x;
cin >> a >> b >> x; // อ่านข้อมูลแยกด้วยช่องว่างหรือบรรทัดใหม่
cout << a << " " << b << " " << x << "\n"; // แสดงผลข้อมูล
| Type | Description | Usage |
|---|---|---|
| int | จำนวนเต็ม 32 บิต | ใช้สำหรับจำนวนไม่เกิน 2 พันล้าน |
| long long | จำนวนเต็ม 64 บิต | ห้ามลืมใช้เมื่อตัวเลขอาจเกิน 2 พันล้าน! |
| double | ทศนิยม 64 บิต | การคำนวณที่ต้องการความแม่นยำสูง |
| bool | ค่าจริงหรือเท็จ | ใช้ในการตรวจสอบเงื่อนไข (true/false) |
ข้อผิดพลาดที่พบบ่อยที่สุด: การเก็บค่าเกินขีดจำกัดของตัวแปร
int a = 123456789;
long long b = a * a; // ผลลัพธ์ผิดพลาด!
long long b = (long long)a * a; // วิธีแก้ไขที่ถูกต้อง
ทศนิยมในคอมพิวเตอร์ไม่สามารถเก็บค่าที่แท้จริงได้เสมอไป
ให้ตรวจสอบว่าผลต่างน้อยกว่าค่าความผิดพลาด (ε) หรือไม่
if (abs(a - b) < 1e-9) { /* เท่ากัน */ }
typedef long long ll;
typedef vector<int> vi;
ช่วยให้ประกาศตัวแปรขนาดใหญ่ได้ในไม่กี่ตัวอักษร
#define F first
#define PB push_back
ระวัง: การใช้ Macro อาจทำให้เกิดข้อผิดพลาดในการ Debug ได้ง่าย
โจทย์มักจะให้หาคำตอบ "Modulo 109 + 7" เพื่อป้องกันตัวเลขล้น
(a + b) % m = (a % m + b % m) % m
(a * b) % m = (a % m * b % m) % m
x = (x % m + m) % m;
ชนิดข้อมูล bool เก็บค่าได้เพียง true (1) หรือ false (0)
! (NOT) — กลับค่า
&& (AND) — และ
|| (OR) — หรือ
== (เท่ากับ), != (ไม่เท่า)
<, > (น้อยกว่า, มากกว่า)
<=, >= (น้อยกว่า/มากกว่าเท่ากับ)
if (condition) {
// ทำงานถ้าเป็นจริง
} else if (other_condition) {
// ทำงานถ้าเงื่อนไขแรกไม่จริงแต่เงื่อนไขนี้จริง
} else {
// ทำงานในกรณีอื่นๆ ทั้งหมด
}
ทิป: การใช้ else if ช่วยให้คอมพิวเตอร์ไม่ต้องตรวจสอบเงื่อนไขที่ซ้ำซ้อนกัน
ใช้เมื่อทราบจำนวนรอบการทำงานที่แน่นอน
for (int i = 0; i < n; i++) {
// ส่วนของ code ที่ต้องการทำซ้ำ
}
ใช้เมื่อต้องการวนลูปจนกว่าเงื่อนไขจะเป็นเท็จ โดยไม่ระบุรอบแน่นอน
while (condition) {
// ทำงานตราบเท่าที่เงื่อนไขเป็นจริง
}
while (cin >> x) ได้
หยุดการทำงานของลูปทันทีและกระโดดออกไปทำคำสั่งหลังลูป
ข้ามการทำงานที่เหลือในรอบปัจจุบัน และเริ่มรอบถัดไปทันที
คำสั่งเหล่านี้ช่วยเพิ่มประสิทธิภาพและทำให้อัลกอริทึมซับซ้อนน้อยลง
int add(int a, int b) {
return a + b;
}
จะมีการ Copy ข้อมูลใหม่ทั้งหมด
เปลืองหน่วยความจำและเวลาถ้าข้อมูลมีขนาดใหญ่
ส่ง "ตำแหน่ง" ของข้อมูลเดิมไป
รวดเร็วกว่าและสามารถแก้ไขค่าต้นฉบับได้
Recursion คือฟังก์ชันที่เรียกใช้งานตัวเองเพื่อแก้ปัญหาย่อย (Subproblems)
int factorial(int n) {
if (n <= 1) return 1; // Base Case
return n * factorial(n - 1); // Recursive Step
}
ปัญหาของการใช้ Recursion แบบปกติคือการคำนวณซ้ำ (Redundant Calculations)
long long memo[6]; // เก็บค่าผลลัพธ์
long long fib(int n) {
if (n <= 1) return n;
if (memo[n] != -1) return memo[n]; // คืนค่าถ้ามีอยู่แล้ว
return memo[n] = fib(n-1) + fib(n-2);
}
เทคนิคนี้เป็นหัวใจของ **Dynamic Programming** ซึ่งจะเรียนลึกขึ้นในวันที่ 5
ประกาศนอกฟังก์ชัน เข้าถึงได้จากทุกที่ อาร์เรย์ที่ประกาศเป็น Global จะถูกล้างค่าเป็น 0 โดยอัตโนมัติ
ประกาศในฟังก์ชัน เข้าถึงได้เฉพาะในฟังก์ชันนั้น ค่าเริ่มต้นจะเป็นค่าขยะ (Random) หากไม่กำหนดค่า
ใช้สำหรับประกาศค่าคงที่ไม่เปลี่ยนแปลง เพื่อป้องกันข้อผิดพลาดและใช้กำหนดขนาดอาร์เรย์
const int MAXN = 100005;
const double PI = 3.1415926535;
MAXN = 200000; // Error! คอมไพล์ไม่ผ่าน
ใช้จัดกลุ่มข้อมูลหลายประเภทที่เกี่ยวข้องกันไว้ด้วยกัน
struct Point {
double x, y;
};
Point p1 = {1.5, 2.0};
มีประโยชน์อย่างมากในการเก็บข้อมูลโจทย์เรขาคณิตหรือสถานะของโหนดในกราฟ
struct Point {
double x, y;
void mirror() { y = -y; } // เปลี่ยนแปลงค่าในตัว
double dist() const { return sqrt(x*x + y*y); }
};
ช่วยให้กำหนดค่าเริ่มต้นให้ struct ได้อย่างรวดเร็ว
struct Edge {
int to, weight;
Edge(int t, int w) : to(t), weight(w) {}
};
adj[u].push_back(Edge(v, w));
ใช้เก็บค่าจริง (true) หรือเท็จ (false) สำหรับตรวจสอบเงื่อนไข
bitset แทนอาร์เรย์ bool เพื่อประหยัดพื้นที่หน่วยความจำได้ถึง 32 เท่า
เก็บตัวอักษร 1 ตัว (8 bits) มีค่าเป็นรหัส ASCII
char c = 'A';
cout << (int)c; // พิมพ์ค่า 65
if (c >= 'A' && c <= 'Z') // ตรวจสอบตัวพิมพ์ใหญ่
จัดการข้อความได้เหมือนอาร์เรย์ของตัวอักษร
s.size(): คืนค่าความยาวข้อความ s + t: เชื่อมต่อข้อความสองอันs[i]: เข้าถึงตัวอักษรตำแหน่งที่ i (เริ่มที่ 0) ใช้เมื่อต้องการอ่านข้อมูลที่มีเว้นวรรคจนจบทั้งบรรทัด
string s;
getline(cin, s);
cin.ignore() เพื่อล้างตัวอักษรขึ้นบรรทัดใหม่ (\n) ก่อนเรียก getline
abs(x)
ค่าสัมบูรณ์sqrt(x)
รากที่สองpow(x, y)
x ยกกำลัง ysin, cos, tan
ตรีโกณมิติceil(x)
ปัดขึ้นfloor(x)
ปัดลงฟังก์ชันเหล่านี้ทำงานกับ double หรือ float
อยู่ในไลบรารี <algorithm> ใช้เปรียบเทียบค่าสองค่า
cout << min(3, 7); // 3
cout << max(10, 5); // 10
cout << min({a, b, c, d}); // (C++11) หาค่าต่ำสุดจากลิสต์
เหตุผลที่ endl ช้ากว่า "\n" อย่างมาก
cout << endl;
1. ขึ้นบรรทัดใหม่cout << "\n";
1. ขึ้นบรรทัดใหม่เท่านั้น (รวบรวมข้อมูลไว้ส่งทีเดียวเมื่อบัฟเฟอร์เต็ม)สำคัญมากในโจทย์ที่ต้องแสดงผลข้อมูลนับแสนบรรทัด
ใช้ตรวจสอบสมมติฐาน (Assumption) ระหว่างเขียนโค้ด
#include <cassert>
assert(n <= 100); // ถ้า n > 100 โปรแกรมจะ Crash ทันที
ตั้งค่า Compiler ให้แจ้งเตือนข้อผิดพลาดที่มองไม่เห็นด้วยตาเปล่า
g++ -Wall -Wextra -O2 main.cpp
"Don’t focus on typing speed as a beginner."
เป็นแหล่งข้อมูลฟรีที่ครอบคลุมเนื้อหาตั้งแต่นักเรียนใหม่จนถึงระดับกลาง รวบรวมทั้งการพิสูจน์ (Proofs) และตัวอย่างโค้ด (Implementations) ที่ใช้งานได้จริง