Cod sursa(job #3251024)

Utilizator redstonegamer22Andrei Ion redstonegamer22 Data 24 octombrie 2024 16:47:30
Problema Secv8 Scor 5
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.16 kb
#pragma GCC optimize("Ofast")
#define LIBCXX_ENABLE_THREADS OFF
#include <bits/stdc++.h>
#include <ext/rope>

using namespace std;
using namespace __gnu_cxx;

#ifndef LOCAL
ifstream in("secv8.in");
ofstream out("secv8.out");
#define cin in
#define cout out
#endif  // LOCAL

#include <iostream>
#include <memory>
#include <cassert>
#include <vector>  // For std::vector

// Modified bump_allocator
template <typename T>
class bump_allocator {
public:
    using value_type = T;

    struct buffer_t {
        char* data;
        std::size_t size;
        std::size_t offset;
    };

    // Static vector of buffers shared among all instances
    static std::vector<buffer_t> buffers;

    static constexpr std::size_t initial_buffer_size = 2 * 1024 * 1024 * sizeof(T);

    // Static initialization flag
    static bool initialized;

    bump_allocator() {
        if (!initialized) {
            allocate_new_buffer(initial_buffer_size);
            initialized = true;
        }
    }

    // Copy constructor for rebind mechanism
    template <typename U>
    bump_allocator(const bump_allocator<U>&) noexcept {
        if (!initialized) {
            allocate_new_buffer(initial_buffer_size);
            initialized = true;
        }
    }

    // Allocate memory for n objects of type T
    T* allocate(std::size_t n) {
        size_t space_required = n * sizeof(T);

        // Try to allocate in the current buffer
        buffer_t& current_buffer = buffers.back();
        if (current_buffer.offset + space_required <= current_buffer.size) {
            T* result = reinterpret_cast<T*>(current_buffer.data + current_buffer.offset);
            current_buffer.offset += space_required;
            return result;
        } else {
            // Allocate a new buffer with increased size (e.g., double the current size)
            std::size_t new_buffer_size = std::max(space_required, current_buffer.size * 2);
            allocate_new_buffer(new_buffer_size);
            // Now allocate from the new buffer
            return allocate(n);  // Recursive call should succeed now
        }
    }

    // Deallocate is a no-op for a bump allocator
    void deallocate(T*, std::size_t) {
        // No-op
    }

    // Resets the allocator (only way to free all memory)
    static void reset() {
        // Free all buffers
        for (auto& buffer : buffers) {
            delete[] buffer.data;
        }
        buffers.clear();
        initialized = false;
    }

    // Construct an object of type T in allocated memory
    template <typename U, typename... Args>
    void construct(U* p, Args&&... args) {
        ::new ((void*)p) U(std::forward<Args>(args)...);  // Placement new
    }

    // Destroy an object of type T
    template <typename U>
    void destroy(U* p) {
        p->~U();  // Explicitly call the destructor
    }

    // Comparison operators (necessary for allocator compatibility)
    bool operator==(const bump_allocator&) const noexcept {
        return true;  // All instances are considered equal (stateless)
    }

    bool operator!=(const bump_allocator& other) const noexcept {
        return !(*this == other);
    }

    // Rebind allocator to a different value type (required for allocator compatibility)
    template <typename U>
    struct rebind {
        using other = bump_allocator<U>;
    };

private:
    // Allocate a new buffer and add it to the buffers vector
    static void allocate_new_buffer(std::size_t buffer_size) {
        buffer_t new_buffer;
        new_buffer.data = new char[buffer_size];
        new_buffer.size = buffer_size;
        new_buffer.offset = 0;
        buffers.push_back(new_buffer);
    }
};

// Initialize static variables
template <typename T>
std::vector<typename bump_allocator<T>::buffer_t> bump_allocator<T>::buffers;

template <typename T>
bool bump_allocator<T>::initialized = false;

// Main function
int main() {
#ifndef LOCAL
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif  // LOCAL

    rope<int, bump_allocator<int>> s;  // Use the updated bump allocator here
    int k, c;
    cin >> k >> c;

    while (k--) {
        char t;
        cin >> t;
        if (t == 'I') {
            int p, x;
            cin >> p >> x;
            p--;
            s.insert(p, x);
            s.insert(s.size() - p, x);
        }
        if (t == 'A') {
            int p;
            cin >> p;
            cout << s[p - 1] << '\n';
        }
        if (t == 'R') {
            int l, r;
            cin >> l >> r;
            l--;
            r--;
            s = s.substr(0, l) + s.substr(s.size() - r - 1, r - l + 1) +
                s.substr(r + 1, s.size() - 2 * r - 2) + s.substr(l, r - l + 1) +
                s.substr(s.size() - l, l);
        }
        if (t == 'D') {
            int l, r;
            cin >> l >> r;
            l--;
            r--;
            s.erase(s.size() - r - 1, r - l + 1);
            s.erase(l, r - l + 1);
        }

#ifdef LOCAL
        cerr << "\t\tS: ";
        for (auto e : s) cerr << e << " ";
        cerr << endl;
#endif  // LOCAL
    }

    s = s.substr(0, s.size() / 2);
    for (auto e : s) cout << e << " ";
    cout << '\n';

    // When done with all allocations
    bump_allocator<int>::reset();

    return 0;
}