Asosiy g‘oya:
«kichik obyektlar ko‘p, lekin ular kichik; katta obyektlar kam»
Og‘ir va yengil obyektlarga bo‘lish
Klassik misol — ildiz bo‘yicha faktorizatsiya.
Agar d≥n — n sonining «katta» bo‘luvchisi bo‘lsa, unga «kichik» bo‘luvchi mos keladi:
dn≤n.
Ya’ni katta bo‘luvchilar kam, chunki har bir kattasiga kichigi mos keladi.
Bunday mantiq ko‘pincha boshqa obyektlarga ham ko‘chiriladi: satrlar, graf cho‘qqilari, so‘rov turlari, buyum og‘irliklari va h.k.
Uzun va qisqa satrlar
Masala
Onlayn tarzda satrlar to‘plamini qo‘llab-quvvatlash va amallarni bajarish kerak:
Satrni to‘plamga qo‘shish
Satrni to‘plamdan o‘chirish
Berilgan satr uchun u to‘plamdagi barcha satrlar orasida nechta marta ostsatr sifatida uchrashini hisoblash
G‘oya
Satrlarni quyidagilarga ajratamiz:
qisqa: ∣s∣<L
uzun: ∣s∣≥L
Bu yerda LS sifatida tanlanadi, bu yerda S — barcha satrlarning umumiy uzunligi.
Shunda uzun satrlar kam: LS=O(S) dan ko‘p emas.
So‘rovlarga qanday javob berish
Qo‘shish/o‘chirish uchun:
satrning barcha qisqa ostsatrlarini ko‘rib chiqamiz
ularning xeshlarini hisoblaymiz va xesh-jadvalni (hisoblagichni) yangilaymiz
3-tur so‘rov:
agar satr qisqa bo‘lsa — shunchaki jadvaldan uning xeshini ko‘ramiz
agar satr uzun bo‘lsa — uni to‘plamdagi barcha satrlar bo‘yicha tekshirishga ruxsat beramiz (chunki uzun so‘rovlar kam bo‘ladi)
Grafdagi uchburchaklar
Masala
n ta cho‘qqi va m≈n ta qirrali graf berilgan. Uzunligi 3 bo‘lgan sikllar (uchburchaklar) sonini hisoblash kerak.
Og‘ir cho‘qqi ta’rifi
Cho‘qqi og‘ir, agar uning darajasi n dan katta bo‘lsa, aks holda yengil.
Og‘ir cho‘qqilar kam: ularning soni O(n) dan ko‘p emas.
Uchburchaklar sonini baholash
Uchburchakdagi og‘ir cho‘qqilar soniga qarab ajratamiz:
Og‘ir cho‘qqilar yo‘q
Uchburchakda (a,b) qirrasi bor, uchinchi cho‘qqi c qo‘shnilar kesishmasi/birlashmasida yotadi.
Darajalar kichik bo‘lgani uchun O(mn) tartibidagi cheklovga ega bo‘lamiz.
Bitta og‘ir
Xuddi shunday: «yengil» qirra bor → baho ham O(mn).
Ikkita og‘ir (a,c) qirrani fiksatsiya qilamiz, usullar O(m).
Og‘ir cho‘qqilar jami O(n → yana .
Uchta og‘ir
Og‘ir cho‘qqilar kam, ko‘rib chiqish ham sig‘adi.
Natijada uchburchaklar «unchalik ko‘p emas»: O(mn) tartibida.
Oddiy yechim (g‘oya)
Cho‘qqilarni (daraja, raqam) bo‘yicha saralaymiz.
Keyin to‘g‘ri tartibda v→u→w ko‘rinishidagi yo‘llarni ko‘rib chiqamiz va v→w qirrasi borligini tekshiramiz.
O(SS) va tezroq ryukzak
Shart
Og‘irliklari w1,…,wn bo‘lgan n ta buyum bor, bunda:
∑wi=S.
Standart dinamika O(S⋅n) da ishlaydi.
Eslatma: turli og‘irliklar kam
Agar yig‘indisi S bo‘lgan k ta turli musbat og‘irlik bo‘lsa, unda:
S≥1+2+⋯+k=2k(k+1)
bundan:
k≤O(S).
Ya’ni turli og‘irliklar O(S) dan ko‘p emas.
Karraliklarni siqish (ikkilik darajalar bo‘yicha ajratish)
Agar x og‘irlik k marta uchrasa, k ni ikkilik darajalar yig‘indisiga ajratamiz va bu k ta buyumni quyidagi og‘irlikdagi buyumlarga almashtiramiz:
x,2x,4x,…
Shu tariqa q≤k uchun q⋅x ko‘rinishidagi barcha yig‘indilar saqlanadi.
Bunday o‘zgartirishdan so‘ng buyumlar soni O(og‘irliklar_soni⋅logS) tartibida bo‘ladi,
so‘ng standart dinamikani ishga tushiramiz.
Eslatma: ryukzak yechimini bitset yordamida ancha tezlashtirish mumkin.
)
O(mn)
long long count_triangles(int n, vector<vector<int>> &g){ vector<int> deg(n); for(int v = 0; v < n; v++) deg[v] =(int)g[v].size(); auto better =[&](int a, int b){ if(deg[a] != deg[b]) return deg[a]< deg[b]; return a < b;}; // sort vertices by (degree, id) vector<int> order(n); iota(order.begin(), order.end(), 0); sort(order.begin(), order.end(), better); // sort adjacency lists in the same order for(int v = 0; v < n; v++){ sort(g[v].begin(), g[v].end(), better);} vector<int> cnt(n, 0); long long ans = 0; for(int v : order){ // mark all "forward" neighbors of v for(int u : g[v]){ if(!better(v, u)) break; cnt[u] = 1;} // count triangles v - u - w where v<u<w in this order for(int u : g[v]){ if(!better(v, u)) break; for(int w : g[u]){ if(!better(u, w)) break; ans += cnt[w];}} // unmark for(int u : g[v]){ if(!better(v, u)) break; cnt[u] = 0;}} return ans;}