Subtask 1 ( )
เราสามารถลองเลือกเอาหนังสือออกในทุกรูปแบบแล้ว เช็คว่าแบบใดที่ตรงกับเงื่อนไขเพื่อหาจำนวนหนังสือที่น้อยที่สุดที่ต้องเอาออก
Time Complexity:
Subtask 2-3
สังเกตว่าการที่เราหาว่าการที่เราหาวิธีการเอาหนังสือออกน้อยที่สุดนั้นทำได้ยาก เราสามารถเปลี่ยนมุมมองของโจทย์เป็นว่าเราจะเก็บหนังสือไว้บนชั้นได้มากที่สุดกี่เล่มแทน โดยโจทย์นี้เราสามารถมองเป็น weight scheduling problem โดยเราสามารถเก็บค่าตำแหน่งของหนังสือเล่มที่อยู่ซ้ายที่สุดกับอยู่ขวาที่สุด และเก็บจำนวนของหนังสือประเภทนั้น เนื่องจากหากเราเลือกจะเก็บหนังสือประเภทใดก็ตาม เราจะไม่สามารถเก็บหนังสือประเภทอื่น ระหว่างเหลื่อมหรือทับกับหนังสือช่วงที่เราจะเลือกเก็บได้
ให้ แทนจำนวนหนังสือที่เก็บได้มากที่สุด เมื่อมองแค่ ช่องแรก
ให้ หนังสือเล่มซ้ายสุดที่มีประเภทเหมือนหนังสือเล่มที่
ให้ จำนวนหนังสือที่มีประเภทเหมือนหนังสือเล่มที่
ถ้าหนังสือเล่มที่ เป็นหนังสือเล่มขวาสุดของหนังสือประเภทนั้น
ถ้าหนังสือเล่มที่ i ไม่ใช่หนังสือเล่มขวาสุดของหนังสือประเภทนั้น
คำตอบของคำถามคือ
Time Complexity:
Subtask 4 ( )
เราสามารถสังเกตเพิ่มเติมจาก Subtask 2-3 ได้ว่าหนังสือที่เราควรจะเลือกออกนั้นจะเป็นหนังสือที่เป็นเล่มที่อยู่ซ้ายสุด หรือขวาสุดของประเภทนั้นๆเท่านั้น โดยเราสามารถ 2D dynamic programming โดยเพิ่มมาหนึ่งมิติเพื่อเก็บว่าเราเคยเอาทำหนังสือออกแค่เล่มเดียวหรือยังในการแก้ไขปัญหา
Time Complexity:
Solution Code:
#include <bits/stdc++.h> using namespace std; #define pb push_back #define F first #define S second int n, m, k, x[1000005], ty[1000005]; int dp[1000005][3], ls[1000005][3], mx[1000005][2], mn[1000005][2]; vector<pair<int, pair<int, int> > > v[1000005]; int main() { scanf("%d %d", &n, &k); for (int i = 1; i <= n; i++) { scanf("%d", &x[i]); if (ty[x[i]] == 0) { mx[x[i]][0] = i; mx[x[i]][1] = i; mn[x[i]][0] = i; mn[x[i]][1] = i; } else { mx[x[i]][1] = mx[x[i]][0]; mx[x[i]][0] = i; if (ty[x[i]] == 1) mn[x[i]][1] = i; } ty[x[i]]++; } for (int i = 1; i <= n; i++) { if (ty[i] == 0) continue; else if (ty[i] == 1) v[mx[i][0]].pb({mn[i][0] - 1, {1, 0}}); else { v[mx[i][0]].pb({mn[i][0] - 1, {ty[i], 0}}); v[mx[i][1]].pb({mn[i][0] - 1, {ty[i] - 1, 1}}); v[mx[i][0]].pb({mn[i][1] - 1, {ty[i] - 1, 1}}); } } for (int i = 1; i <= n; i++) { for (int j = 0; j < v[i].size(); j++) { if (v[i][j].S.S == 1) { for (int cc = 1; cc < 3; cc++) { if (dp[i][cc] < dp[v[i][j].F][cc - 1] + v[i][j].S.F && ls[v[i][j].F][cc - 1] != x[i]) { dp[i][cc] = dp[v[i][j].F][cc - 1] + v[i][j].S.F; ls[i][cc] = x[i]; } } } else { for (int cc = 0; cc < 3; cc++) { if (dp[i][cc] < dp[v[i][j].F][cc] + v[i][j].S.F) { dp[i][cc] = dp[v[i][j].F][cc] + v[i][j].S.F; } } } } for (int cc = 0; cc < 3; cc++) { if (dp[i][cc] < dp[i - 1][cc]) { dp[i][cc] = dp[i - 1][cc]; ls[i][cc] = ls[i - 1][cc]; } } } int ans = 0; for (int i = 0; i <= k; i++) ans = max(ans, dp[n][i]); printf("%d", n - ans); }