When we only have queries and swaps (no range updates), the problem becomes trivial. We can maintain a simple array and perform operations directly:
A[i] in O(1)A[i] and A[j] in O(1)This approach is straightforward since we don't need to handle range updates.
This subtask requires efficient range updates and point queries - a classic problem solved with the difference array technique:
Maintain a difference array in a Fenwick Tree where we store diff[i] = A[i] - A[i-1].
Key Insight: If diff[i] = A[i] - A[i-1], then A[i] = diff[1] + diff[2] + ... + diff[i] (prefix sum).
Operations:
diff[l] += xdiff[r+1] -= xWith small constraints, a naive approach works perfectly:
A[i] in O(1)A[i] and A[j] in O(1)This brute-force solution is acceptable since Q·N ≤ 4·10^6.
The full problem requires handling both swaps and range updates efficiently. The challenge is combining the difference array technique with swaps.
Approach: Fenwick Tree with Difference Array
We maintain a BIT storing the difference array: diff[i] = A[i] - A[i-1].
Operations:
Type 1 (Query position i):
A[i] = prefix_sum(i) = sum of diff[1..i]Type 3 (Range update [l, r] by x):
Type 2 (Swap positions l and r) - The Key Insight:
val_l = get(l), val_r = get(r)d = val_l - val_rdiff[l] -= d (decrease A[l] by d)diff[l+1] += d (cancel effect after position l)diff[r] += d (increase A[r] by d)diff[r+1] -= d (cancel effect after position r)Why this works for swaps: By using the difference array, we can modify a single position without affecting others by updating at position i and canceling at position i+1.
#include <bits/stdc++.h>
using namespace std;
class FenwickTree {
private:
vector<long long> tree;
int size;
public:
FenwickTree(int n) : size(n), tree(n + 1, 0) {}
// Add delta to position pos
void update(int pos, long long delta) {
for (; pos <= size; pos += pos & (-pos)) {
tree[pos] += delta;
}
}
// Get prefix sum from 1 to pos
long long query(int pos) {
long long sum = 0;
for (; pos > 0; pos -= pos & (-pos)) {
sum += tree[pos];
}
return sum;
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
FenwickTree bit(n);
// Initialize difference array: diff[i] = A[i] - A[i-1]
long long previous = 0;
for (int i = 1; i <= n; i++) {
long long current;
cin >> current;
bit.update(i, current - previous);
previous = current;
}
// Process queries
for (int i = 0; i < q; i++) {
int type;
cin >> type;
if (type == 1) {
// Query: get value at position pos
int pos;
cin >> pos;
cout << bit.query(pos) << '\n';
} else if (type == 2) {
// Swap: exchange values at positions left and right
int left, right;
cin >> left >> right;
long long value_left = bit.query(left);
long long value_right = bit.query(right);
long long difference = value_left - value_right;
// Update differences to swap values
bit.update(left, -difference);
bit.update(left + 1, difference);
bit.update(right, difference);
bit.update(right + 1, -difference);
} else {
// Range update: add x to all elements in [left, right]
int left, right;
long long x;
cin >> left >> right >> x;
bit.update(left, x);
bit.update(right + 1, -x);
}
}
return 0;
}