Broj inverzija
Dat je niz od n različitih brojeva od 1 do n (permutacija, n ≤ 2·105). Inverzija je par i < j za koji je a[i] > a[j]. Koliko ima inverzija?
Primer
Ulaz
5
2 4 1 3 5Izlaz
3Fenwick stablo (Binary Indexed Tree) održava niz i odgovara na pitanje „koliki je zbir prvih k elemenata?“ – i to dok se elementi menjaju. Obe operacije traju O(log n), a kod je kratak: desetak redova.
Dat je niz od n brojeva i q upita dve vrste: promeni element na poziciji i i koliki je zbir na intervalu [l, r]. Običan niz daje izmenu u O(1), a zbir u O(n). Prefiksni zbirovi daju zbir u O(1), ali izmenu u O(n). Za n, q do 2·105 oba pristupa su prespora, a Fenwick stablo radi oba upita u O(log n).
Pozicije su od 1 do n. Element bit[i] čuva zbir dela niza koji se završava na i, a dužina tog dela je najniži bit broja i: lowbit(i) = i & (-i). Na primer, bit[12] čuva zbir pozicija 9–12 (12 = 1100₂, najniži bit je 4), a bit[7] samo poziciju 7.
bit[i], pa pređi na i -= lowbit(i), dok i > 0.bit[i], pa pređi na i += lowbit(i), dok i ≤ n.U oba slučaja broj koraka je najviše broj bitova, tj. O(log n).
#include <iostream>
#include <vector>
using namespace std;
int n;
vector<long long> bit;
void dodaj(int i, long long x) { // a[i] += x
for (; i <= n; i += i & (-i)) bit[i] += x;
}
long long prefiks(int i) { // a[1] + ... + a[i]
long long s = 0;
for (; i > 0; i -= i & (-i)) s += bit[i];
return s;
}
int main() {
int q;
cin >> n >> q;
bit.assign(n + 1, 0);
vector<long long> a(n + 1);
for (int i = 1; i <= n; i++) { cin >> a[i]; dodaj(i, a[i]); }
while (q--) {
int tip;
cin >> tip;
if (tip == 1) { // 1 i v : a[i] = v
int i; long long v;
cin >> i >> v;
dodaj(i, v - a[i]); // dodajemo razliku
a[i] = v;
} else { // 2 l r : zbir a[l..r]
int l, r;
cin >> l >> r;
cout << prefiks(r) - prefiks(l - 1) << "\n";
}
}
return 0;
}
Izmena „postavi na v“ se pretvara u „dodaj razliku v − a[i]“, pa zato čuvamo i sam niz a.
Fenwick je kraći i brži, ali prirodno radi samo za operacije koje imaju „suprotnu“ (zbir – oduzimanje, XOR). Za minimum, maksimum ili složenije upite na intervalu koristi se segmentno stablo.
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
Dat je niz od n različitih brojeva od 1 do n (permutacija, n ≤ 2·105). Inverzija je par i < j za koji je a[i] > a[j]. Koliko ima inverzija?
5
2 4 1 3 53Prodavnica beleži prodaju za n dana (u početku 0). Upiti: P d k – dana d prodato je još k komada; Z a b – koliko je ukupno prodato od dana a do dana b?
5 4
P 2 3
P 4 5
Z 1 3
Z 2 53
8prefiks(r) − prefiks(l − 1).int – koristi long long.1. Koliko je 12 & (-12)?
2. Kolika je složenost upita za zbir prvih k elemenata?
3. Koji upit Fenwick ne podržava direktno?