主要思路
刚开始看到分治的标签就下定决心用分治做,没一会发现信息非常难利用就弃疗了。考虑用类似于 KMP 的 AC 自动机的方法完成本题。
首先设置\(dp[i]\)为以\(i\)开头向右延伸的答案,那么我们往左的时候可以合并之,并设置\(nxt[i]\)来进行跳跃;由于得到\(nxt\)数组的过程暴力做时间复杂度会 GG,所以我们可以使用类似 AC 自动机的方式用 Map 合并信息:交换\(nxt[i]+1\)位置的 Map 并设置当前位置。最后做 DP 即可。
代码
// CF1240D.cpp
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX_N = 3e5 + 200;
int q, n, ai[MAX_N], nxt[MAX_N], dp[MAX_N];
map<int, int> nxt_map[MAX_N];
ll ans;
int main()
{
scanf("%d", &q);
while (q--)
{
scanf("%d", &n), ans = 0;
for (int i = 1; i <= n; i++)
scanf("%d", &ai[i]);
for (int i = 1; i <= n + 2; i++)
nxt[i] = -1, dp[i] = 0, nxt_map[i].clear();
for (int i = n; i >= 1; i--)
{
if (nxt_map[i + 1].count(ai[i]))
{
int pos = nxt_map[i + 1][ai[i]];
if (pos <= n && ai[i] == ai[pos])
{
nxt[i] = pos, swap(nxt_map[i], nxt_map[pos + 1]);
if (pos <= n - 1)
nxt_map[i][ai[pos + 1]] = pos + 1;
}
}
nxt_map[i][ai[i]] = i;
}
for (int i = n; i >= 1; i--)
if (nxt[i] != -1)
dp[i] = 1 + dp[nxt[i] + 1], ans += dp[i];
printf("%lld\n", ans);
}
return 0;
}
// CF1240D.cpp
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX_N = 3e5 + 200;
int q, n, ai[MAX_N], nxt[MAX_N], dp[MAX_N];
map<int, int> nxt_map[MAX_N];
ll ans;
int main()
{
scanf("%d", &q);
while (q--)
{
scanf("%d", &n), ans = 0;
for (int i = 1; i <= n; i++)
scanf("%d", &ai[i]);
for (int i = 1; i <= n + 2; i++)
nxt[i] = -1, dp[i] = 0, nxt_map[i].clear();
for (int i = n; i >= 1; i--)
{
if (nxt_map[i + 1].count(ai[i]))
{
int pos = nxt_map[i + 1][ai[i]];
if (pos <= n && ai[i] == ai[pos])
{
nxt[i] = pos, swap(nxt_map[i], nxt_map[pos + 1]);
if (pos <= n - 1)
nxt_map[i][ai[pos + 1]] = pos + 1;
}
}
nxt_map[i][ai[i]] = i;
}
for (int i = n; i >= 1; i--)
if (nxt[i] != -1)
dp[i] = 1 + dp[nxt[i] + 1], ans += dp[i];
printf("%lld\n", ans);
}
return 0;
}
// CF1240D.cpp #include <bits/stdc++.h> #define ll long long using namespace std; const int MAX_N = 3e5 + 200; int q, n, ai[MAX_N], nxt[MAX_N], dp[MAX_N]; map<int, int> nxt_map[MAX_N]; ll ans; int main() { scanf("%d", &q); while (q--) { scanf("%d", &n), ans = 0; for (int i = 1; i <= n; i++) scanf("%d", &ai[i]); for (int i = 1; i <= n + 2; i++) nxt[i] = -1, dp[i] = 0, nxt_map[i].clear(); for (int i = n; i >= 1; i--) { if (nxt_map[i + 1].count(ai[i])) { int pos = nxt_map[i + 1][ai[i]]; if (pos <= n && ai[i] == ai[pos]) { nxt[i] = pos, swap(nxt_map[i], nxt_map[pos + 1]); if (pos <= n - 1) nxt_map[i][ai[pos + 1]] = pos + 1; } } nxt_map[i][ai[i]] = i; } for (int i = n; i >= 1; i--) if (nxt[i] != -1) dp[i] = 1 + dp[nxt[i] + 1], ans += dp[i]; printf("%lld\n", ans); } return 0; }