题意
给出⼀个⻓度为&n&的正整数串 。现在可以把两个没有重叠的连续⼦串前后拼接起来,但是要求拼接之后的
数串中每个正整数不能出现超过 次。请问能拼接出来的符合要求的数字串的最⼤⻓度是多少。
n <= 1e6
1 <= a_i <= 18
先把所有可能的分段都记录下来,时间复杂度n*18
状压后暴力枚举子集,都没有进行状态转移,其实没有用到DP。
关键是这个枚举
for (int i = 0; i < (1 << 18); i++) {
for (int j = i; j > 0; j = j - 1 & i) {
ans = max(ans,f[j] + f[i^j]);
}
}
j-1&i 可以可高效从大到小枚举子集
f[i^j]是与f[i]互补的子集
3^n 时间复杂度? 因为每一位如果仅仅是遍历而不枚举子集本来是有0和1两种情况,2^n
枚举子集的情况,1位多了一种情况,共两种:在子集中出现,没有在子集中出现,所以一位一共有三种情况。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define _ cout << "----------" << endl
//#define int ll
void solve() {
int n;
cin >> n;
vector<int> a(n+1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
vector<int> f(1 << 18);
for (int i = 1; i <= n; i++) {
int cnt = 0;
for (int j = i; j <= min(n,i+18); j++) {
if (cnt & ((1 << (a[j] - 1)))) {
break;
}
cnt |= (1 << (a[j]-1));
f[cnt] = j - i + 1;
}
}
int ans = 0;
for (int i = 0; i < (1 << 18); i++) {
for (int j = i; j > 0; j = j - 1 & i) {
ans = max(ans,f[j] + f[i^j]);
}
}
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt = 1;
//cin >> tt;
while (tt--) {
solve();
}
return 0;
}