【题解】「COCI 2024.1」Milano C.le [附 LIS 模版]

【题解】「COCI 2024.1」Milano C.le [附 LIS 模版]
P10225 [COCI 2023/2024 #3] Milano C.le - 洛谷 (luogu.com.cn)不难发现能放在同一个站台的 ab 点对和必须满足且。转化成二维表格平面图就是一条单调下降的线最后有多少条这样的线就有多少个站台。进一步我们发现这些线的起始端点必须连成一条单调上升的线不然两条线就能并成一条。所以最后求的就是以为下标排序集合里最长上升子序列的长度。话说到这个 LIS 啊老久没看了已经更新换代到我有点不认识的版本了。LIS 模板代码长这样// hs 个人见解有错指出 // hansang 是我以前笔名proMatheus 是现用名 #includebits/stdc.h using namespace std; const int N 2e5 10; int a[N], b[N]; int len 0; int main () { ios::sync_with_stdio(false); cin.tie(0); int n; cin n; for (int i 1; i n; i ) { cin a[i]; } /* 我们需要维护一个 b 数组 其中 b[i] 代表当前上升子序列长度为 i 时可能的最小数值注意不是下标 定义 len 为当前 LIS最长上升子序列 的长度 按顺序遍历 a 数组时如果 a[i] b[len] 说明 a[i] 可以直接接在现有的 LIS 后面 反则 a[i] 替换 b 数组中第一个大于或等于它的数 有人会问了判断条件时不是只用到 b[len] 吗 为什么还要更新 b 数组里别的数 如果每次 a[i] b[len] 时都只用 a[i] 更新 b[len] 那怎么保证 a[i] b[len - 1] 呢 由此可得要维护整个 b 数组的递增关系 综上一个贪心加二分时间复杂度 O(nlogn)相当不错 */ len 0; b[len] 0; for (int i 1; i n; i ) { if (a[i] b[len]) { len ; b[len] a[i]; } else { *lower_bound(b 1, b len 1, a[i]) a[i]; } } cout len \n; return 0; }本题 ac 代码#includebits/stdc.h using namespace std; const int N 2e5 10; int a[N], b[N], t[N]; int bb[N]; int main () { ios::sync_with_stdio(false); cin.tie(0); int n; cin n; for (int i 1; i n; i ) { cin a[i]; } for (int i 1; i n; i ) { cin b[i]; } for (int i 1; i n; i ) { t[a[i]] b[i]; } int len 0; bb[len] 0; for (int i 1; i n; i ) { if (t[i] bb[len]) { len ; bb[len] t[i]; } else { *lower_bound(bb 1, bb len 1, t[i]) t[i]; } } cout len \n; return 0; }