Pagini recente » Cod sursa (job #1541545) | Cod sursa (job #2813873) | Cod sursa (job #1592970) | Cod sursa (job #2985584) | Cod sursa (job #2055195)
#include <cassert>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <memory>
#include <numeric>
using namespace std;
class Reader {
public:
Reader(istream& _in) : in(_in), idx(kBuffSize - 1), buff(new char[kBuffSize]) { Advance(); }
Reader& operator>>(char& ch) {
ch = Current();
Advance();
return *this;
}
Reader& operator>>(char str[]) {
while (isspace(Current())) {
Advance();
}
int n = 0;
while (not isspace(Current())) {
str[n++] = Current();
Advance();
}
str[n] = 0;
return *this;
}
Reader& operator>>(string& str) {
while (isspace(Current())) {
Advance();
}
while (not isspace(Current())) {
str.push_back(Current());
Advance();
}
return *this;
}
Reader& operator>>(int32_t& value) {
bool sign = false;
while (not isdigit(Current())) {
sign |= Current() == '-';
Advance();
}
value = 0;
while (isdigit(Current())) {
value = (value << 1) + (value << 3) + (Current() - '0');
Advance();
}
value ^= (value ^ -value) & -sign;
return *this;
}
Reader& operator>>(int64_t& value) {
bool sign = false;
while (not isdigit(Current())) {
sign |= Current() == '-';
Advance();
}
value = 0;
while (isdigit(Current())) {
value = (value << 1) + (value << 3) + (Current() - '0');
Advance();
}
value ^= (value ^ -value) & -sign;
return *this;
}
Reader& operator>>(double& value) {
bool sign = false;
while (not isdigit(Current())) {
sign |= Current() == '-';
Advance();
}
value = .0;
while (isdigit(Current())) {
value = value * 10.0 + (Current() - '0');
Advance();
}
if (Current() == '.') {
Advance();
double multiplier = 0.1;
while (isdigit(Current())) {
value += (Current() - '0') * multiplier;
multiplier *= 0.1;
Advance();
}
}
if (sign) {
value = -value;
}
return *this;
}
private:
static constexpr int kBuffSize = 1 << 12;
char Current() const {
return buff[idx];
}
void Advance() {
if (++idx == kBuffSize) {
in.read(buff.get(), kBuffSize);
idx = 0;
}
}
istream& in;
int idx;
unique_ptr<char[]> buff;
};
class Printer {
public:
Printer(ostream& _out) : out(_out), idx(0), buff(new char[kBuffSize]), digits(new char[kMaxNumDigits]) { }
~Printer() { Flush(); out.flush(); }
Printer& operator<<(int32_t value) {
if (value < 0) {
PutChar('-');
value = -value;
}
int num_digits = 0;
do {
const uint32_t aux = ((uint64_t)3435973837 * value) >> 35;
digits[num_digits++] = value - (aux << 1) - (aux << 3) + '0';
value = aux;
} while (value > 0);
while (num_digits--) {
PutChar(digits[num_digits]);
}
return *this;
}
Printer& operator<<(int64_t value) {
if (value < 0) {
PutChar('-');
value = -value;
}
int num_digits = 0;
do {
const uint64_t aux = value / 10;
digits[num_digits++] = value - (aux << 1) - (aux << 3) + '0';
value = aux;
} while (value > 0);
while (num_digits--) {
PutChar(digits[num_digits]);
}
return *this;
}
Printer& operator<<(const char *str) {
for (int i = 0; str[i]; i += 1) {
PutChar(str[i]);
}
return *this;
}
Printer& operator<<(const string& str) {
for (auto&& ch : str) {
PutChar(ch);
}
return *this;
}
Printer& operator<<(const char& ch) {
PutChar(ch);
return *this;
}
Printer& operator <<(double value) {
if (value < 0) {
PutChar('-');
value = -value;
}
const int64_t integer_part = static_cast<int64_t>(value);
*this << integer_part << '.' << static_cast<int64_t>((value - integer_part) * kPrecision + 0.5);
return *this;
}
private:
static constexpr int kBuffSize = 1 << 12;
static constexpr int kMaxNumDigits = 20;
static constexpr double kPrecision = 1e9;
void Flush() {
out.write(buff.get(), idx);
}
void PutChar(const char& ch) {
buff[idx++] = ch;
if (idx == kBuffSize) {
Flush();
idx = 0;
}
}
ostream& out;
int idx;
unique_ptr<char[]> buff, digits;
};
class DisjointSets {
public:
DisjointSets(const int n = 0) : x(n, -1), max_idx(n) { iota(max_idx.begin(), max_idx.end(), 0); }
bool Unite(int a, int b) {
a = FindRoot(a);
b = FindRoot(b);
if (a != b) {
if (x[b] < x[a]) {
x[b] += x[a];
x[a] = b;
if (max_idx[b] < max_idx[a]) {
max_idx[b] = max_idx[a];
}
} else {
x[a] += x[b];
x[b] = a;
if (max_idx[a] < max_idx[b]) {
max_idx[a] = max_idx[b];
}
}
return true;
}
return false;
}
int FindRoot(const int node) {
return x[node] < 0 ? node : x[node] = FindRoot(x[node]);
}
int GetMaxIdx(const int node) {
return max_idx[FindRoot(node)];
}
private:
vector<int> x, max_idx;
};
template<typename T>
class LinkedList {
public:
LinkedList(const int n = 0, const int m = 0) : head(n, kNil), next(m), buff(m), buff_idx(0) { }
void Clear() {
fill(head.begin(), head.end(), kNil);
}
void Push(const int where, const T& value) {
buff[buff_idx] = value;
next[buff_idx] = head[where];
head[where] = buff_idx;
buff_idx += 1;
}
T& operator[](const int idx) {
return buff[idx];
}
int Advance(const int position) const {
return next[position];
}
int Front(const int where) const {
return head[where];
}
static constexpr int kNil = -1;
private:
vector<int> head, next;
vector<T> buff;
int buff_idx;
};
template<class T>
vector<int> OfflineRMQ(const vector<T>& vec,
vector<pair<int, int>>& ranges) {
int n = static_cast<int>(vec.size()), q = static_cast<int>(ranges.size());
LinkedList<int> queries(n, q);
for (int i = 0; i < (int)ranges.size(); i += 1) {
queries.Push(ranges[i].second, ranges[i].first);
}
ranges.clear();
DisjointSets DS(n);
vector<int> stk;
vector<int> answer(q);
for (int i = 0; i < n; i += 1) {
while (not stk.empty() and vec[stk.back()] >= vec[i]) {
DS.Unite(stk.back(), i);
stk.pop_back();
}
stk.push_back(i);
for (auto left = queries.Front(i); left != queries.kNil; left = queries.Advance(left)) {
answer[left] = DS.GetMaxIdx(queries[left]);
}
}
return answer;
}
int main() {
#ifdef INFOARENA
ifstream cin("rmq.in");
ofstream cout("rmq.out");
#endif
cin.tie(0);
ios_base::sync_with_stdio(false);
Reader r(cin); Printer p(cout);
int n, q; r >> n >> q;
vector<int> values(n);
for (auto& x : values) {
r >> x;
}
vector<pair<int, int>> ranges(q);
for (auto& q : ranges) {
r >> q.first >> q.second;
q.first -= 1; q.second -= 1;
}
auto&& answers = OfflineRMQ(values, ranges);
for (auto&& query_answer : answers) {
p << values[query_answer] << '\n';
}
}