Let's denote:
Key Observation: The value at position (1-indexed) in array is determined by the position of the lowest set bit (trailing zeros) in . Specifically, if position has trailing zeros in its binary representation, then .
Editorial: When all elements are equal to some constant , every position in array has value . Therefore:
Time Complexity: per query
Space Complexity:
Editorial: These queries ask for the sum of the entire array built after rounds. We can use the recurrence:
This is because , so the new sum is twice the old sum plus .
Time Complexity: per query
Space Complexity:
Editorial: For small , we can actually construct the array explicitly since . Then we can compute prefix sums and answer each query in .
Time Complexity:
Space Complexity:
Editorial: For a point query at position , we need to find which element of is at position . The key insight is that where is the number of trailing zeros in the binary representation of (equivalently, the position of the lowest set bit, 0-indexed from right).
Algorithm:
Example:
Time Complexity: per query
Space Complexity:
Editorial: The key insight is to compute prefix sums efficiently without building the array. For a position (1-indexed), we can compute by analyzing the binary representation of .
Mathematical Insight: The contribution of each to the prefix sum can be computed by examining the bits of :
where .
The algorithm works as follows:
To answer a query : compute .
Why this works: Each element appears at positions where the number of trailing zeros equals . The number of such positions in the first positions follows a pattern based on the binary representation of . The term counts occurrences, and subtracting the previous element's contribution accounts for the transition between levels.
Time Complexity: per query
Space Complexity:
function getValue(p):
k = __builtin_ctzll(p) // count trailing zeros
return a[k]
#include <bits/stdc++.h>
using namespace std;
const int64_t MOD = 1e9 + 7;
int64_t a[99], n;
int64_t mul(int64_t x, int64_t y) {
x = (x % MOD + MOD) % MOD;
y = (y % MOD + MOD) % MOD;
return (x * y) % MOD;
}
int64_t add(int64_t x, int64_t y) {
return (MOD + (x + y) % MOD) % MOD;
}
// Compute prefix sum for positions 1 to pos
int64_t prefixSum(int64_t pos) {
int64_t ans = 0, prev = 0;
for (int i = 0; i < n && pos > 0; i++) {
ans = add(ans, mul(-pos, prev));
ans = add(ans, mul(pos, a[i]));
prev = a[i];
pos /= 2;
}
return ans;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int q;
cin >> q;
while (q--) {
int64_t l, r;
cin >> l >> r;
cout << add(prefixSum(r), -prefixSum(l - 1)) << '\n';
}
return 0;
}