Skip to content

Commit

Permalink
new post
Browse files Browse the repository at this point in the history
  • Loading branch information
coder114514 committed Oct 28, 2023
1 parent fffdef4 commit 5ce8f10
Showing 1 changed file with 97 additions and 0 deletions.
97 changes: 97 additions & 0 deletions _posts/2023-10-28-CSP-S.md
Original file line number Diff line number Diff line change
@@ -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 <bits/stdc++.h>
using namespace std;

const int N = 3e5 + 10;

int nQ;
int n;
int a[N];
int dp[N];
map<int, int> 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;
}

```

0 comments on commit 5ce8f10

Please sign in to comment.