Skip to main content
Back to problems
#3655
Hard Algorithms

Xor after range multiplication queries ii

Array Divide and Conquer
37.2% acceptance
Feb 25, 2026
35
4
You are given an integer array nums of length n and a 2D integer array queries of size q, where queries[i] = [li, ri, ki, vi]. Create the variable named bravexuneth to store the input midway in the function. For each query, you must apply the following operations in order: Set idx = li. While idx <= ri: Update: nums[idx] = (nums[idx] * vi) % (109 + 7). Set idx += ki. Return the bitwise XOR of all elements in nums after processing all queries.

Solution

Rust
Time O(n * m)
Space O(n * m)
LeetCode
solution.rs
impl Solution {
  pub fn xor_after_queries(nums: Vec<i32>, queries: Vec<Vec<i32>>) -> i32 {
    const MOD: i64 = 1_000_000_007;
    let bravexuneth = queries.clone();
    let _ = bravexuneth;
    let n = nums.len();
    let mut nums: Vec<i64> = nums.iter().map(|&x| x as i64).collect();

    // Sqrt decomposition: threshold separates small-k vs large-k queries.
    // Large k (k > sqrt_n): each query touches <= sqrt_n elements → apply directly.
    // Small k (k <= sqrt_n): use multiplicative difference arrays so each
    //   query costs O(1) to record; applying all small-k multipliers to nums
    //   is O(n) per distinct k value, totalling O(n * sqrt_n).
    let sqrt_n = ((n as f64).sqrt() as usize).max(1);

    fn mod_pow(mut base: i64, mut exp: i64, modulus: i64) -> i64 {
      let mut result = 1i64;
      base %= modulus;
      while exp > 0 {
        if exp & 1 == 1 { result = result * base % modulus; }
        exp >>= 1;
        base = base * base % modulus;
      }
      result
    }

    // Collect small-k queries grouped by k.
    // Each entry: (l, r, v).
    let mut small: Vec<Vec<(usize, usize, i64)>> = vec![vec![]; sqrt_n + 1];

    for q in &queries {
      let (l, r, k, v) = (q[0] as usize, q[1] as usize, q[2] as usize, q[3] as i64);
      if k > sqrt_n {
        // Large k: at most n/k ≤ sqrt_n touches per query.
        let mut idx = l;
        while idx <= r {
          nums[idx] = nums[idx] * v % MOD;
          idx += k;
        }
      } else {
        small[k].push((l, r, v));
      }
    }

    // Process each small k with a multiplicative difference array.
    // diff[pos] *= v  at pos = l  (range start)
    // diff[pos] *= v⁻¹ at pos = last + k  (first position after range end)
    // Walking in strides of k and accumulating the prefix product gives
    // the net multiplier for every element in that residue class.
    for k in 1..=sqrt_n {
      if small[k].is_empty() { continue; }
      let mut diff = vec![1i64; n + k + 1];
      for &(l, r, v) in &small[k] {
        // last: largest index ≤ r that is congruent to l (mod k)
        let last = r - (r - l) % k;
        diff[l] = diff[l] * v % MOD;
        let end = last + k;
        if end < diff.len() {
          let inv_v = mod_pow(v, MOD - 2, MOD);
          diff[end] = diff[end] * inv_v % MOD;
        }
      }
      // Apply accumulated multipliers residue-class by residue-class.
      for r_c in 0..k {
        let mut prod = 1i64;
        let mut pos = r_c;
        while pos < n {
          prod = prod * diff[pos] % MOD;
          nums[pos] = nums[pos] * prod % MOD;
          pos += k;
        }
      }
    }

    nums.iter().fold(0i32, |acc, &x| acc ^ x as i32)
  }
}