Acwing 3485. 最大异或和
https://www.acwing.com/problem/content/description/3488/
题意:n个数,在区间长度最长为m的情况下,求最大连续异或值。
思路:连续异或值只要将前缀和存储起来再异或即可。对于限制了区间长度的连续异或值,可以将区间的前缀和放到树中,使用滑动窗口把区间外的前缀和移出去即可。
总结:没注意到前缀异或的性质,在这个滑动窗口内,就算是从0开始的前缀和,也不影响在这个窗口内的前缀值计算。
发现,在存数和删数的时候,用int整数传更好用。
而且好像string和bitset有tle风险。
struct Node{
array<int, 2> next;
int cnt;
Node():cnt(0), next{}{}
};
class Trie{
public:
Trie():root_(0){
trie_.resize(1);
}
void insert(int x){
int cur = root_;
for (int i = 30; i >= 0; --i){
int p = (x >> i) & 1;
if (trie_[cur].next[p] == 0){
trie_[cur].next[p] = (int)trie_.size();
trie_.emplace_back();
}
cur = trie_[cur].next[p];
trie_[cur].cnt ++;
}
}
void erase(int x){
int cur = root_;
for (int i = 30; i >= 0; --i){
int p = (x >> i) & 1;
cur = trie_[cur].next[p];
trie_[cur].cnt --;
}
}
int get(int x){
int cur = root_;
int res = 0;
for (int i = 30; i >= 0; --i){
int p = (x >> i) & 1;
if (trie_[cur].next[!p] == 0 && trie_[cur].next[p] == 0){
break;
}
if(trie_[cur].next[!p] && trie_[trie_[cur].next[!p]].cnt > 0){
res += 1 << i;
cur = trie_[cur].next[!p];
}
else{
cur = trie_[cur].next[p];
}
}
return res;
};
private:
int root_;
vector<Node> trie_;
};
void solve(){
int n, m;
cin >> n >> m;
vector<int> a(n);
for (auto& x : a){
cin >> x;
}
vector<int> pref(n + 1);
for (int i = 0; i < n; ++i){
pref[i + 1] = pref[i] ^ a[i];
}
Trie trie{};
trie.insert(0);
int ans = 0;
for (int i = 1; i <= n; ++i){
if (i > m){
trie.erase(pref[i - m - 1]);
}
ans = max(ans, trie.get(pref[i]));
trie.insert(pref[i]);
}
cout << ans << endl;
}

浙公网安备 33010602011771号