F. Korney Korneevich and XOR (hard version)
给一个长度为n的数列a[],求所有递增子序列的不同的异或值
a i ≤ 5000 , n ≤ 1 e 6 a_i \le 5000, n\le 1e6 ai≤5000,n≤1e6
F1 的 subtask, a i ≤ 500 , n ≤ 1 e 5 a_i \le 500 , n \le 1e5 ai≤500,n≤1e5 直接向后转移
#include <bits/stdc++.h>
using namespace std;
const int N = 550;
const int inf = 0x3f3f3f3f;
int f[N];
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
memset(f, 0x3f, sizeof f);
f[0] = 0;
int n;
cin >> n;
for (int i = 1, x; i <= n; ++i) {
cin >> x;
for (int j = 0; j < N; ++j) {
if (f[j] < x)
f[j ^ x] = min(f[j ^ x], x);
}
}
vector<int> res;
for (int i = 0; i < N; ++i)
if (f[i] != inf) res.push_back(i);
cout << res.size() << endl;
for (auto x: res) cout << x << " ";
}
记录每个ai的位置
复杂度:5000 * (1 << 13) * math.log(1e6) 其实挺卡的
#include <bits/stdc++.h>
using namespace std;
const int N = (1 << 13);
const int M = 1e6 + 10;
const int inf = 0x3f3f3f3f;
int f[N]; // f[i]:=异或和为i的序列中最后一个数最小是多少
vector<int> g[N]; //g[i]:= i的位置
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
memset(f, 0x3f, sizeof f);
f[0] = 0;
int n;
cin >> n;
for (int i = 1, x; i <= n; ++i) {
cin >> x;
g[x].push_back(i);
}
for (int i = 0; i <= 5000; ++i) {
for (int j = 0; j < N; ++j) {
auto it = upper_bound(g[i].begin(), g[i].end(), f[j]);
if (it != g[i].end()) f[i ^ j] = min(f[i ^ j], (*it));
}
}
vector<int> res;
for (int i = 0; i < N; ++i)
if (f[i] != inf) res.push_back(i);
cout << res.size() << endl;
for (auto x: res) cout << x << " ";
}