From 5ce8f1024633555c578e1ace605e1f8cc29692c0 Mon Sep 17 00:00:00 2001 From: coder114514 <98397499+coder114514@users.noreply.github.com> Date: Sun, 29 Oct 2023 00:11:08 +0800 Subject: [PATCH] new post --- _posts/2023-10-28-CSP-S.md | 97 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 _posts/2023-10-28-CSP-S.md diff --git a/_posts/2023-10-28-CSP-S.md b/_posts/2023-10-28-CSP-S.md new file mode 100644 index 0000000..7bbd057 --- /dev/null +++ b/_posts/2023-10-28-CSP-S.md @@ -0,0 +1,97 @@ +--- +title: CSP-S 2023 复赛 +last_modified_at: 2023/09/20 +tags: OI +--- + +考场上 T1, T3 做出来了 + +T2, T4 CF 上有原题 + +# T2 +[原题](https://codeforces.com/contest/1223/problem/F) + +令 $f_i$ 从 $i$ 开头的可消去子串的数量 + +$nxt_i$ 是使得 $\left[i,j\right]$ 可消去的最小的 $j$ + +那么 $f_i=f_{nxt_i+1}+1$ 如果 $nxt_i$ 存在,否则是 $0$ + +$nxt_i$ 可以这么求($nxt_i$ 存在的话): +``` +nxt[i] := i+1 +while a[nxt[i]] != a[i]: + nxt[i] = nxt[nxt[i]] + 1 +``` + +但是这么做是 $O(n^2)$ 的,不能拿满分 + +所以引入 $nxta_{i,x}$ 表示使得 $\left[i,j\right]$ 可消去且 $a_{j+1}=x$ 的最小的 $j$ + +那么就有这样的关系 + +若 $nxt_i$ 和 $nxta_{i,x}$ 都存在 + +当 $a_i==a_{i+1}$ 时 $nxt_i=i+1$ 否则 $nxt_i=nxta_{i+1,a_i}+1$ + +当 $x==a_{nxt_i+1}$ 时 $nxta_{i,x}=nxt_i$ 否则 $nxta_{i,x}=nxta_{nxt_i+1,x}$ + +原题的代码:(CCF版缩小了值域 +$nxt$ 为 $1$,$nxta$ 为 $0$ 表示不存在 +```cpp +#include +using namespace std; + +const int N = 3e5 + 10; + +int nQ; +int n; +int a[N]; +int dp[N]; +map nxta[N]; + +void input() { + scanf("%d", &n); + for (int i = 1; i <= n; i++) + scanf("%d", &a[i]); +} + +void solve() { + for (int i = n + 1; i >= 1; i--) { + nxta[i].clear(); + dp[i] = 0; + } + for (int i = n - 1; i >= 1; i--) { + int nxt; + if (a[i] == a[i + 1]) { + nxt = i + 1; + nxta[i] = move(nxta[nxt + 1]); + if (nxt + 1 <= n) nxta[i][a[nxt + 1]] = nxt; + dp[i] = dp[nxt + 1] + 1; + } else { + nxt = nxta[i + 1][a[i]] + 1; + if (nxt != 1) { + nxta[i] = move(nxta[nxt + 1]); + if(nxt + 1 <= n) nxta[i][a[nxt + 1]] = nxt; //*** + dp[i] = dp[nxt + 1] + 1; + } + } + } + long long ans = 0; //*** + for (int i = 1; i < n; i++) { + ans += dp[i]; + } + cout << ans << endl; +} + +int main() { + scanf("%d", &nQ); + for (int iQ = 1; iQ <= nQ; iQ++) { + input(); + solve(); + } + return 0; +} + +``` +