Pagini recente » Cod sursa (job #1880591) | Cod sursa (job #2058638) | Cod sursa (job #295073) | Cod sursa (job #936867) | Cod sursa (job #2497785)
#include <fstream>
#include <bitset>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
using namespace std;
class parser {
public:
inline parser() {
/// default c-tor
}
inline parser(const char* file_name) {
int fd = open(file_name, O_RDONLY);
index &= 0;
fstat(fd, &sb);
buffer = (char*)mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
close(fd);
}
template <typename T>
inline parser& operator >> (T& n) {
n &= 0;
#ifdef SIGNED
sign &= 0;
sign = (buffer[index - 1] == '-');
#endif
for (; buffer[index] < '0' or buffer[index] > '9'; ++index);
for (; '0' <= buffer[index] and buffer[index] <= '9'; ++index)
n = (n << 3) + (n << 1) + buffer[index] - '0';
#ifdef SIGNED
n ^= ((n ^ -n) & -sign);
#endif
return *this;
}
~parser() {
munmap(buffer, sb.st_size);
}
private:
struct stat sb;
int index;
#ifdef SIGNED
int sign;
#endif
char* buffer;
};
class writer {
public:
writer() {};
writer(const char* file_name) {
output_file.open(file_name, std::ios::out | std::ios::binary);
output_file.sync_with_stdio(false);
index &= 0;
}
template <typename T>
inline writer& operator <<(T target) {
auto inc = [&, this]() mutable {
if (++index == SIZE)
index &= 0,
output_file.write(buffer, SIZE);
};
aux &= 0;
#ifdef SIGNED_WRITE
sign = 1;
if (target < 0)
sign = -1;
#endif // SIGNED_WRITE
if (target == 0) {
buffer[index] = '0';
inc();
return *this;
}
for (; target; target = target / 10)
#ifndef SIGNED_WRITE
nr[aux++] = target % 10 + '0';
#else
nr[aux++] = (sign * target) % 10 + '0';
if (sign == -1)
buffer[index] = '-', inc();
#endif // SIGNED_WRITE
for (; aux; inc())
buffer[index] = nr[--aux];
return *this;
}
inline writer& operator <<(const char* target) {
auto inc = [&, this]() mutable {
if (++index == SIZE)
index &= 0,
output_file.write(buffer, SIZE);
};
aux &= 0;
while (target[aux])
buffer[index] = target[aux++], inc();
return *this;
}
inline void close() {
delete this;
}
~writer() {
output_file.write(buffer, index);
output_file.close();
}
private:
static const int SIZE = 0x200000; ///2MB
int index, aux;
#ifdef SIGNED_WRITE
int sign;
#endif // SIGNED_WRITE
char buffer[SIZE], nr[24];
std::fstream output_file;
};
//#define DYNAMIC_ALLOC
template <class _elem, typename compare_by = std::less<int>>
class heap { /// expects functor
/// compare is expected to return bool value
/// by-default min_heap, change compare function accordingly
public:
heap(size_t _size = 1024) {
max_size = _size;
storage = new _elem[max_size];
current_bound = 1;
}
heap(const heap<_elem, compare_by>& target) { *this = target; }
heap& operator = (const heap<_elem, compare_by>& target) {
delete[] storage;
max_size = target.max_size;
storage = new _elem[max_size];
for (unsigned i = 0; i < max_size; ++i)
storage[i] = target.storage[i];
current_bound = target.current_bound;
}
[[gnu::hot]] inline void add(_elem target) {
storage[current_bound] = target;
sift_up(current_bound);
#ifdef DYNAMIC_ALLOC
if (++current_bound == max_size) {
max_size <<= 1;
realloc(storage, max_size);
}
#else
++current_bound;
#endif
}
[[gnu::pure]] inline bool empty() { return (current_bound == 1); }
[[gnu::pure]] inline _elem top() { return storage[1]; }
[[gnu::hot]] inline _elem pop() {
storage[0] = storage[1];
storage[1] = storage[current_bound - 1];
sift_down(1);
current_bound--;
return storage[0];
}
~heap() { delete[] storage; }
private:
[[gnu::hot]] inline void sift_up(unsigned crawler) {
_elem aux = storage[crawler];
while (parent_pos(crawler) && comparator(aux, parent(crawler))) {
storage[crawler] = parent(crawler);
crawler = parent_pos(crawler);
}
storage[crawler] = aux;
}
[[gnu::hot]] inline void sift_down(unsigned crawler) {
_elem aux = storage[crawler];
while (!is_leaf(crawler)) {
if (comparator(aux, left_son(crawler))) {
storage[crawler] = left_son(crawler);
crawler = left_son_pos(crawler);
}
else if (comparator(aux, right_son(crawler))) {
storage[crawler] = right_son(crawler);
crawler = right_son_pos(crawler);
}
else {
break;
}
}
storage[crawler] = aux;
}
[[gnu::hot, gnu::pure]] inline unsigned right_son_pos(unsigned pos) {
return 1 + (pos << 1);
}
[[gnu::hot, gnu::pure]] inline _elem right_son(unsigned pos) {
return storage[right_son_pos(pos)];
}
[[gnu::hot, gnu::pure]] inline unsigned left_son_pos(unsigned pos) {
return (pos << 1);
}
[[gnu::hot, gnu::pure]] inline _elem left_son(unsigned pos) {
return storage[left_son_pos(pos)];
}
[[gnu::hot, gnu::pure]] inline unsigned parent_pos(unsigned pos) {
return (pos >> 1);
}
[[gnu::hot, gnu::pure]] inline _elem parent(unsigned pos) {
return storage[parent_pos(pos)];
}
[[gnu::hot]] inline bool is_leaf(unsigned pos) {
return right_son_pos(pos) < current_bound && left_son_pos(pos) < current_bound;
}
compare_by comparator;
size_t max_size, current_bound;
_elem* storage;
};
class integer {
public:
int elem, index;
struct do_compare {
[[gnu::hot, gnu::pure]] inline bool operator () (integer const& a, integer const& b) {
return a.elem < b.elem;
}
};
};
parser f("heapuri.in");
writer t("heapuri.out");
int n;
bitset <200010> vaz;
heap<integer, integer::do_compare> h(200010);
integer maneuver;
int main() {
f >> n;
maneuver.index &= 0;
for (int query, i = 0; i < n; ++i) {
f >> query;
switch (query) {
case 1: {
f >> maneuver.elem;
++maneuver.index;
h.add(maneuver);
break;
}
case 2: {
f >> query;
vaz[query] = true;
break;
}
case 3: {
while (vaz[h.top().index]) {
h.pop();
}
t << h.top().elem << "\n";
break;
}
}
}
return 0;
}