PROBLEM LINK:
Contest Division 1
Contest Division 2
Contest Division 3
Contest Division 4
Setter: Yahor Dubovik
Tester: Harris Leung
Editorialist: Trung Dang
DIFFICULTY:
2444
PREREQUISITES:
XOR, Two Pointers
PROBLEM:
EXPLANATION:
As with any cyclic shift problem, let’s duplicate the array A so that A_{N + i} = A_i for every 1 \le i \le N. We create the array B on this duplicated A similarly: B_i = A_1 \oplus A_2 \oplus \dots \oplus A_i for all 1 \le i \le 2N.
Claim: The number of distinct values on the subarray B_{[i , i + N - 1]} is the value of the array A left-shifted by i - 1 (for any 1 \le i \le N).
To see why, note that the elements of this subarray is [X \oplus A_i, X \oplus A_i \oplus A_{i + 1}, \dots, X \oplus A_i \oplus A_{i + 1} \oplus \dots \oplus A_N \oplus A_1 \oplus \dots \oplus A_{i + N - 1}], where X = B_{i - 1}. We notice that XOR-ing every element in an array does not change the number of distinct elements in this array, so the number of distinct elements in B_{[i , i + N - 1]} is the number of distinct elements in [A_i, A_i \oplus A_{i + 1}, \dots, A_i \oplus A_{i + 1} \oplus \dots \oplus A_N \oplus A_1 \oplus \dots \oplus A_{i + N - 1}], which is exactly the value of A left-shifted by i - 1.
Therefore, the problem becomes simple: we need to find the largest number of distinct elements on all subarrays of size N in B, which can easily be done using sliding window and some straightforward data structure storing occurences of values (such as std::map
).
TIME COMPLEXITY:
Time complexity is O(N \log N).
SOLUTION:
Setter's Solution
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;
typedef long double ld;
typedef long long ll;
const int maxN = 1e6 + 10;
ll a[maxN];
ll pref[maxN];
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
//freopen("input.txt", "r", stdin);
int tst;
cin >> tst;
while (tst--) {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
pref[i + 1] = pref[i] ^ a[i];
}
map<ll,int> mp;
int mx = 0;
int dist = 0;
for (int i = 1; i <= n; i++) {
dist += (mp[pref[i]] == 0);
mp[pref[i]]++;
}
mx = dist;
for (int i = 1; i <= n; i++) {
dist -= (mp[pref[i]] == 1);
mp[pref[i]]--;
dist += (mp[pref[i] ^ pref[n]] == 0);
mp[pref[i] ^ pref[n]]++;
mx = max(mx, dist);
}
cout << mx << '\n';
}
return 0;
}
Tester's Solution
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
const int N=2e5+1;
const int iu=30;
map<ll,int>mp;
int n;
ll a[N];
ll ans=0;
ll f=0;
void solve(){
cin >> n;
mp.clear();
ans=f=0;
for(int i=1; i<=n ;i++){
cin >> a[i];
a[i]^=a[i-1];
f+=mp[a[i]]++==0;
}
ans=f;
for(int i=1; i<=n ;i++){
f-=--mp[a[i]]==0;
f+=mp[a[i]^a[n]]++==0;
ans=max(ans,f);
}
cout << ans << '\n';
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int t;cin >> t;while(t--) solve();
}
Editorialist's Solution
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t; cin >> t;
while (t--) {
int n; cin >> n;
vector<long long> a(n);
map<long long, int> occ;
int cnt = 0;
long long prf = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
prf ^= a[i];
if (occ[prf]++ == 0) {
cnt++;
}
}
long long tot = prf;
int ans = 0;
for (int i = 0; i < n; i++) {
prf ^= a[i];
if (occ[prf]++ == 0) {
cnt++;
}
if (--occ[prf ^ tot] == 0) {
cnt--;
}
ans = max(ans, cnt);
}
cout << ans << '\n';
}
}