TGViewer
Поступашки - Информатика Поступашки - Информатика @postupashki_prog · 1.75K subscribers
Post #121 4.14K
С наступающим, камрады. Сегодня разберём оффлайн-решение RMQ (минимум на отрезке) с помощью монотонного стека и DSU.
Задача
Дан массив a[0..n-1] и q запросов (l, r). Нужно для каждого запроса найти min(a[l..r]). Все запросы известны заранее (оффлайн).

Идея
Будем идти по правой границе r слева направо: r = 0, 1, 2, …, n-1.
В момент, когда мы дошли до позиции r, мы хотим уметь быстро отвечать на запросы, у которых правая граница равна этому r: (l, r). Если бы мы умели поддерживать для каждого l индекс минимума на отрезке [l..r], то ответ был бы просто a[minIndex].
И как раз это и будет делать DSU: после обработки r, find(l) будет возвращать индекс минимума на [l..r].
Как поддерживать минимум для всех l сразу:
Используем монотонный стек индексов. В стеке значения a по индексам идут по возрастанию (снизу вверх). Когда мы добавляем новый элемент a[r], мы выкидываем из стека все индексы x, для которых a[x] > a[r]. Получается если a[x] > a[r], то для любого отрезка, который заканчивается в r и начинается в позиции l ≤ x, элемент x уже не может быть минимумом на этом отрезке (потому что справа есть меньший a[r]). Более того, r становится “кандидатом минимума” вместо x для многих стартов l. Если просто выкидывать из стека, нам всё равно сложно понять, для каких именно l минимум “переехал” на r. Тогда с помощью DSU будем хранить переходы: если раньше минимум для l был в x, а x оказался больше нового a[r], то теперь минимум для l станет там же, где минимум для x, а это в итоге должно вести на r”. Когда индекс x вылетает из стека из-за a[r], мы делаем parent[find(x)] = r. То есть все l, которые сейчас через DSU указывают на x как на минимум, теперь должны указывать на r. После этого любой запрос (l, r) отвечается одной операцией find(l).

Тогда сгруппируем запросы по правой границе r: для каждого r храним список всех l, которые спрашивают (l, r).
Потом идём r слева направо, обновляем стек и DSU, и сразу отвечаем на все запросы с этой правой границей.



#include <bits/stdc++.h>
using namespace std;

struct Query { int l, id; };

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);

int n, q;
cin >> n >> q;
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];

// запросы сгруппированы по правой границе
vector<vector<Query>> byR(n);
for (int id = 0; id < q; id++) {
int l, r;
cin >> l >> r;
if (l > r) swap(l, r);
// если вход 1-based, то сделайте: --l; --r;
byR[r].push_back({l, id});
}

vector<int> parent(n), ans(q);

function<int(int)> findp = [&](int v) -> int {
if (parent[v] == v) return v;
return parent[v] = findp(parent[v]);
};

vector<int> st; // монотонный стек индексов
st.reserve(n);

for (int r = 0; r < n; r++) {
parent[r] = r; // минимум на [r..r] это r

// выкидываем всё, что больше текущего значения
while (!st.empty() && a[st.back()] > a[r]) {
parent[findp(st.back())] = r;
st.pop_back();
}
st.push_back(r);

// отвечаем на запросы, у которых правая граница равна r
for (auto [l, id] : byR[r]) {
ans[id] = a[findp(l)];
}
}

for (int i = 0; i < q; i++) {
cout << ans[i] << "\n";
}
}


Каждый индекс один раз добавляется в стек и один раз из него удаляется, значит работа со стеком O(n). DSU с сжатием путей даёт почти O(1) (обратная аккермана от n) на find, итого O((n + q) · alpha(n)).

@postupashki_prog
More from @postupashki_prog
  1. Sep 30, 2026Здравствуйте, камрады 😎 Сегодня прокачанная версия бинпоиска по ответу — параллельный бин…
  2. Sep 27, 2026Олимпиады по информатике 2026/27: сколько теперь реально стоит диплом Здравствуйте, камрад…
  3. Sep 21, 2026💻 Камрады, а вы знали, что БВИ на программную инженерию можно было получить по экономике?…
  4. Sep 7, 2026Здравствуйте, товарищи😎 Сегодня разбираем один из самых частотных приёмов - бинарный поис…
  5. Jul 7, 2026Появился новый бот со шпаргалками и бесплатными материалами для подготовки к ОГЭ и ЕГЭ 😱…
  6. Jul 6, 2026Convex Hull Trick Сегодня обсудим одну из самых краисвых техник в алгоритмическом программ…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →