1
+ /* *
2
+ * @file
3
+ * @brief Implementation to [calculate XOR of sliding window of size k in an array of n integers]
4
+ * (https://cses.fi/problemset/task/3426)
5
+ *
6
+ * @details
7
+ * We are given an array of n integers. Our task is to calculate the bitwise XOR of each
8
+ * window of k elements, from left to right, and cumulatively XOR the results into a single value.
9
+ *
10
+ * Worst Case Time Complexity: O(n)
11
+ * Space Complexity: O(n)
12
+ *
13
+ * @author [Abhiraj Mandal](https://github.com/DataWorshipper)
14
+ */
15
+
16
+ #include < cassert> // / for assert
17
+ #include < cstdint>
18
+ #include < vector>
19
+ #include < iostream> // / for IO operations
20
+
21
+ /* *
22
+ * @namespace bit_manipulation
23
+ * @brief Bit manipulation algorithms
24
+ */
25
+ namespace bit_manipulation {
26
+ /* *
27
+ * @namespace sliding_window_xor
28
+ * @brief Functions for cumulative XOR of sliding windows in arrays
29
+ */
30
+ namespace sliding_window_xor {
31
+
32
+ /* *
33
+ * @brief Computes cumulative XOR of all windows of size k
34
+ *
35
+ * @param n Size of the array
36
+ * @param k Window size
37
+ * @param x Initial value to generate the array
38
+ * @param a Multiplier in array generation
39
+ * @param b Increment in array generation
40
+ * @param c Modulo in array generation
41
+ * @returns std::uint64_t The cumulative XOR of all windows of size k
42
+ *
43
+ * @details
44
+ * This function generates the array using the recurrence:
45
+ * arr[0] = x
46
+ * arr[i] = (a * arr[i-1] + b) % c
47
+ *
48
+ * It maintains a sliding window of size k using two pointers l and r:
49
+ * - x1 stores the XOR of the current window
50
+ * - x2 stores the cumulative XOR of all valid windows
51
+ *
52
+ * This approach ensures that the algorithm runs in O(n) time.
53
+ */
54
+ std::uint64_t compute (
55
+ std::uint64_t n,
56
+ std::uint64_t k,
57
+ std::uint64_t x,
58
+ std::uint64_t a,
59
+ std::uint64_t b,
60
+ std::uint64_t c) {
61
+
62
+ // Generate the array of n elements
63
+ std::vector<std::uint64_t > arr (n);
64
+ arr[0 ] = x; // First element of the array
65
+
66
+ for (std::uint64_t i = 1 ; i < n; ++i) {
67
+ arr[i] = (a * arr[i - 1 ] + b) % c; // recurrence relation
68
+ }
69
+
70
+ std::uint64_t x1 = 0 ; // XOR of the current window
71
+ std::uint64_t x2 = 0 ; // Cumulative XOR of all windows of size k
72
+ std::uint64_t l = 0 ; // Left pointer of sliding window
73
+ std::uint64_t r = 0 ; // Right pointer of sliding window
74
+
75
+ // Slide the window over the array
76
+ while (r < n) {
77
+ x1 ^= arr[r]; // include current element in window XOR
78
+
79
+ // Shrink window from left if size exceeds k
80
+ while (r - l + 1 > k) {
81
+ x1 ^= arr[l]; // remove leftmost element from window XOR
82
+ ++l;
83
+ }
84
+
85
+ // If window size equals k, add it to cumulative XOR
86
+ if (r - l + 1 == k) {
87
+ x2 ^= x1;
88
+ }
89
+
90
+ ++r; // Move right pointer
91
+ }
92
+
93
+ return x2; // Return cumulative XOR of all windows
94
+ }
95
+
96
+ } // namespace sliding_window_xor
97
+ } // namespace bit_manipulation
98
+
99
+ /* *
100
+ * @brief Self-test implementation
101
+ */
102
+ static void test () {
103
+ using bit_manipulation::sliding_window_xor::compute;
104
+
105
+ // Testcase 1: n = 100, k = 20, expected = 1019
106
+ assert (compute (100 , 20 , 3 , 7 , 1 , 997 ) == 1019 );
107
+
108
+ // Testcase 2: n = 2, k = 1, expected = 2
109
+ assert (compute (2 , 1 , 2 , 3 , 4 , 5 ) == 2 );
110
+
111
+ // Testcase 3: n = 5, k = 2
112
+ assert (compute (5 , 2 , 1 , 1 , 1 , 100 ) == 0 ^ 3 ^ 1 ^ 7 );
113
+
114
+ // Testcase 4: n = 3, k = 5, expected = 0
115
+ assert (compute (3 , 5 , 5 , 2 , 1 , 100 ) == 0 );
116
+
117
+ // Testcase 5: n = 4, k = 4, expected = 0
118
+ assert (compute (4 , 4 , 3 , 1 , 0 , 10 ) == 0 );
119
+
120
+ std::cout << " All test cases successfully passed!" << std::endl;
121
+ }
122
+
123
+ /* *
124
+ * @brief Main function
125
+ * @returns 0 on exit
126
+ */
127
+ int main () {
128
+ test (); // run self-test implementations
129
+ return 0 ;
130
+ }
0 commit comments