Cod sursa(job #2055203)

Utilizator mlc_oficialBoris Barca mlc_oficial Data 2 noiembrie 2017 22:43:43
Problema Range minimum query Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 7.17 kb
#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<class T>
vector<int> OfflineRMQ(const vector<T>& vec, int q, Reader& r) {
    int n = static_cast<int>(vec.size());
    vector<vector<pair<int, int>>> queries(n);
    for (int i = 0; i < q; i += 1) {
        int left, right; r >> left >> right; left -= 1; right -= 1;
        queries[right].emplace_back(left, i);
    }
     
    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[i]) {
            answer[left.second] = DS.GetMaxIdx(left.first);
        }
    }
    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;
    }
     
    auto&& answers = OfflineRMQ(values, q, r);
    for (auto&& query_answer : answers) {
        p << values[query_answer] << '\n';
    }
}