ข้อสอบท้ายค่าย 2 ปีการศึกษา 2566 ศูนย์ สอวน. มหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี ข้อ Stock
Author: Nagorn Phongphasura
Problem
สรุปโจทย์
มีวันอยู่ทั้งหมด \(N\) วัน แต่ละวัน หุ้นจะมีราคา \(P_i\) บาท ซีเคสามารถซื้อขายหุ้นได้หลายรอบ แต่ใน 1 วันจะซื้อหรือขายได้เพียงรอบเดียว(หรือไม่ซื้อขายหุ้นเลยก้ได้)
สิ่งที่ต้องทำ
หากำไรที่มากที่สุดจากการซื้อขายหุ้น
Constraints
\(2 \leq N \leq 10^5\)
\(0 \leq P_1,P_2,...,P_N \leq 10^9\)
Prerequisites
Math
Solution
Claim: ผลรวมของกำไรที่มากที่สุดที่เป็นไปได้ มีค่าเท่ากับ
Proof: สมมติให้ลำดับการซื้อขายหุ้นที่จะทำให้ได้กำไรมากที่สุด คือการซื้อที่ตำแหน่ง \(\{i_1, i_2, ..., i_k\}\) และขายที่ตำแหน่ง \(\{j_1, j_2, ..., j_k\}\)
สำหรับแต่ละรอบการซื้อขาย \( (i_m, j_m) \) กำไรของรอบนั้นจะเป็น
ซึ่งเท่ากับ ผลรวมของราคาที่เพิ่มขึ้น ในทุกๆคู่วันที่อยู่ติดกัน
แต่ว่า ถ้าในวันไหนราคาลดลง การซื้อขายในวันนั้นจะทำให้ได้กำไร \(\leq 0\) เราจึงไม่ควรขายหุ้นในวันนั้น
ดังนั้น กำไรที่สูงที่สุดที่เป็นไปได้ คือการรวมผลต่างของราคาในวันที่ราคาเพิ่มขึ้น (\(p_{i+1} - p_i > 0\))
จะได้ สูตรหากำไรที่สูงที่สุด คือ
ดังนั้น วิธีทำโจทย์ข้อนี้ คือ Loop ตั้งแต่ 1 ถึง \(N - 1\) แล้วในแต่ละรอบ เพิ่มค่าคำตอบไปด้วย \(max(0, p_{i + 1} - p_i)\)
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int32_t main() {
cin.tie(NULL)->sync_with_stdio(false);
// input
int n;
cin >> n;
vector <int> p(n + 1);
for (int i = 1; i <= n; i++) cin >> p[i];
int ans = 0; // เก็บผลรวมคำตอบ
// Loop เพื่อคำนวณ
for (int i = 1; i < n; i++) {
ans += max(0ll, p[i + 1] - p[i]);
}
// Output
cout << ans << "\n";
return 0;
}
Total Time Complexity
\(O(N)\)