N (≤100,000) 人,每人屬性 S, B。若 S1
維護 dp[len] = 長度為 len 的遞增子序列最小末尾值。
對每個 B,二分查找第一個 ≥ B 的位置替換,或追加。
同時記錄前驅重構路徑。
#include#include #include using namespace std; const int MAXN = 100010; struct Person { int id, S, B; bool operator<(const Person& o) const { return S < o.S || (S == o.S && B > o.B); } } p[MAXN]; int buf[MAXN], dp[MAXN], pre[MAXN], pos[MAXN]; int main() { int n; while (~scanf("%d", &n)) { for (int i = 1; i <= n; ++i) { scanf("%d%d", &p[i].S, &p[i].B); p[i].id = i; } sort(p+1, p+n+1); for (int i = 1; i <= n; ++i) buf[i] = p[i].B; memset(dp, 0x3f, sizeof(dp)); memset(pre, -1, sizeof(pre)); int len = 0; for (int i = 1; i <= n; ++i) { int k = lower_bound(dp+1, dp+len+1, buf[i]) - dp; dp[k] = buf[i]; pre[i] = pos[k-1]; pos[k] = i; if (k > len) len = k; } printf("%d ", len); // 重構輸出路徑(略) puts(""); } return 0; }
lower_bound 求嚴格遞增(≥ 替換)pos[len] 和 pre[i] 可重構具體方案此題是「二維偏序 → 排序 + 一維 LIS」的教科書級應用。