记录我心路历程吧,这道小水题暴露出我不少问题。ios
给定 $n$ 个字符串长度 $a_i$ ,求字符集最小多大,才能构造出按字典序比较 $s_1 < s_2 < \dots < s_n$。c++
当 $a_i < a_{i+1}$ 时,显然全补 $0$ 就行。不然,是一个高精度 $+1$。二分字符集大小,判断行不行。code
如下是我作题过程。blog
首先,除了二分部分,所有推出来了。可是加法的细节写烂了,各类没判。ci
而后没有特判字符集为 $1$ 的状况,硬是跑了 1e9 差点T。(最后改改仍是T了)字符串
而后考虑贪心的过程,写了一个错的。在字符不够的时候新开一个,实际上会致使前面的浪费。it
blog 写到最后发现仍是一道sb题,就当水了一个 blog 吧。io
#include <bits/stdc++.h> const int MAXN = 500010; int n, st[MAXN], col[MAXN], top; void add() { if (st[top] > 1 && st[top - 1] != st[top] - 1) { st[top + 1] = st[top]; col[top + 1] = col[top]; --st[top]; ++top; } ++col[top]; } int A[MAXN]; bool judge(int cnt) { int lst = 0; memset(st, 0, top + 1 << 2); memset(col, 0, top + 1 << 2); top = 0; for (int i = 1, t; i <= n; ++i) { t = A[i]; if (lst < t) { if (!top || col[top] != 0) st[++top] = t, col[top] = 0; else st[top] = t; } else { int k = -1; while (st[top] > t) k = col[top], --top; if (st[top] != t) st[++top] = t, col[top] = k; if (cnt > 1) { add(); while (top && col[top] >= cnt) { int at = st[top]; --top; if (st[top] + 1 != at) st[++top] = at - 1; add(); } } else top = 0, col[0] = 1; if (col[0]) return false; if (st[top] != t) st[++top] = t, col[top] = 0; } lst = t; } return true; } int main() { std::ios_base::sync_with_stdio(false), std::cin.tie(0); std::cin >> n; for (int i = 1; i <= n; ++i) std::cin >> A[i]; int l = 1, r = n, ans = 0; while (l <= r) { int mid = l + r >> 1; if (judge(mid)) ans = mid, r = mid - 1; else l = mid + 1; } std::cout << ans << std::endl; return 0; }