Header Ad

HackerEarth XOR in Sequence problem solution

In this HackerEarth XOR in Sequence problem, we have given a sequence A consisting of N integer elements: A1, A2, .., AN.

Your task is to answer Q queries. Each query requires to count the number of pairs of integers (i, j) such that 1 ≤ i ≤ j ≤ N, and L ≤ Ai XOR Ai + 1 XOR Ai + 2 XOR ... XOR Aj ≤ R where L and R are given.

HackerEarth XOR in Sequence problem solution


HackerEarth XOR in Sequence problem solution.

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 100000 + 10;
const int MAXQ = 100 + 10;

int a[MAXN];
int n, q;
vector<int> bits[2 * MAXQ];

struct trie {
int c;
trie* next[2];
trie(int _c) {
c = _c;
next[0] = next[1] = NULL;
}
};

trie* root;

int get_bit(int j, int i) {
return (i >> (j - 1)) & 1;
}

vector<int> analys(int x) {
vector<int> res(30);
for(int i = 1; i <= 30; i++) res[30 - i] = get_bit(i, x);
return res;
}

int calc(vector<int> &a, vector<int> &b) {
trie* curr = root;
int res = 0;
for(int i = 0; i < 30; i++) {
int j = a[i] ^ b[i], k = a[i] ^ (1 - j);
if ((k < b[i]) && (curr->next[1 - j] != NULL)) res += curr->next[1 - j]->c;
if (curr->next[j] == NULL) break;
curr = curr->next[j];
}
return res;
}

void push(vector<int> &a) {
trie* curr = root;
for(int i = 0; i < 30; i++) {
if (curr->next[a[i]] == NULL) curr->next[a[i]] = new trie(1);
else curr->next[a[i]]->c++;
curr = curr->next[a[i]];
}
}

int main()
{
int test;
cin >> test;
assert((1 <= test) && (test <= 10));
while (test --) {
cin >> n;
assert((1 <= n) && (n <= 100000));
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
assert((1 <= a[i]) && (a[i] <= 1000000000));
}
cin >> q;
assert((1 <= q) && (q <= 10));
vector<int> b;
for(int i = 0; i < q; i++) {
int l, r;
cin >> l >> r;
assert((0 <= l) && (l <= r) && (r <= 1000000000));
b.push_back(l); b.push_back(r + 1);
}
for(int i = 0; i < b.size(); i++) bits[i] = analys(b[i]);
vector<long long> S(b.size());
root = new trie(0);
vector<int> c = analys(0);
push(c);
int sum_xor = 0;
for(int i = 1; i <= n; i++) {
sum_xor ^= a[i];
c = analys(sum_xor);
for(int i = 0; i < b.size(); i++) S[i] += calc(c, bits[i]);
push(c);
}
for(int i = 0; i < q; i++) printf("%lld\n", S[i * 2 + 1] - S[i * 2]); //cout << S[i * 2 + 1] - S[i * 2] << endl;
}
}

Second solution

#include <algorithm>
#include <memory.h>
#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <cassert>
#include <map>
#include <set>
#include <vector>
#include <queue>

using namespace std;
#define prev privet1
#define next privet2
#define y1 privet3
#define rank privet4
#define left privet5
#define right privet6
#define y0 privet7

const double pi = 3.141592653589793238;

void ensureLimit(long long n, long long l, long long r) {
assert(l <= n && n <= r);
}

const int MAX_N = 100333;

int n, cnt;
int a[MAX_N];
int trie[2][MAX_N * 30], subtreeSize[MAX_N * 30];


void add(int x) {
int v = 1, bit;
for (int i = 29; i >= 0; i--) {
if (x & (1 << i)) {
bit = 1;
}
else {
bit = 0;
}
if (trie[bit][v] == 0) {
cnt++;
trie[bit][v] = cnt;
}
subtreeSize[trie[bit][v]]++;
v = trie[bit][v];
}
}

int count(int x, int m) {
int v = 1, bitx, bitm, res = 0;
for (int i = 29; i >= 0; i--) {
if (x & (1 << i)) {
bitx = 1;
}
else {
bitx = 0;
}
if (m & (1 << i)) {
bitm = 1;
}
else {
bitm = 0;
}
if (bitx == 0 && bitm == 0) {
if (trie[0][v] == 0) {
return res;
}
v = trie[0][v];
}
else if (bitx == 1 && bitm == 0) {
if (trie[1][v] == 0) {
return res;
}
v = trie[1][v];
}
else if (bitx == 0 && bitm == 1) {
res += subtreeSize[trie[0][v]];
if (trie[1][v] == 0) {
return res;
}
v = trie[1][v];
}
else {
res += subtreeSize[trie[1][v]];
if (trie[0][v] == 0) {
return res;
}
v = trie[0][v];
}
}
return res;
}


long long countLess(int m) {
memset(trie, 0, sizeof(trie));
memset(subtreeSize, 0, sizeof(subtreeSize));
cnt = 1;
int tmp = 0;
long long res = 0;
add(0);
for (int i = 1; i <= n; i++) {
tmp ^= a[i];
res += count(tmp, m);
add(tmp);
}
return res;
}

void solve() {
scanf("%d", &n);
ensureLimit(n, 1, 100000);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
ensureLimit(a[i], 1, 1000000000);
}
int queries;
scanf("%d", &queries);
ensureLimit(queries, 1, 10);
while (queries--) {
int l, r;
scanf("%d%d", &l, &r);
ensureLimit(l, 0, r);
ensureLimit(r, l, 1000000000);
printf("%lld\n", countLess(r + 1) - countLess(l));
}
}

int main() {
int tc;
scanf("%d", &tc);
ensureLimit(tc, 1, 10);
while (tc--) {
solve();
}
}


Post a Comment

0 Comments