제출 #952917

#제출 시각아이디문제언어결과실행 시간메모리
952917SirCovidThe19thThe short shank; Redemption (BOI21_prison)C++17
80 / 100
2004 ms80924 KiB
/*
*       ___
*   _ /    _\_
*  / |    |___|
*  | |       |
*  \_|   __  |
*     \_/  \_/
*   uwu amogus
*/
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
 
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x7FFFFFFF
#define llinf 0x7FFFFFFFFFFFFFFF
#define ff first
#define ss second
#define FOR(i, a, b) for(int i = a; i < b; i++)
#define ROF(i, a, b) for(int i = a - 1; i >= b; i--)
//#define assert void
//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#define int ll

#ifndef __OY_FASTIO__
#define __OY_FASTIO__
#define cin OY::IO::InputHelper::get_instance()
#define cout OY::IO::OutputHelper::get_instance()
#define endl '\n'
namespace OY {
    namespace IO {
        using size_type = size_t;
        static constexpr size_type INPUT_BUFFER_SIZE = 1 << 16, OUTPUT_BUFFER_SIZE = 1 << 16, MAX_INTEGER_SIZE = 20, MAX_FLOAT_SIZE = 50;
#ifdef OY_LOCAL
        static constexpr char input_file[] = "in.txt", output_file[] = "out.txt";
#else
        static constexpr char input_file[] = "", output_file[] = "";
#endif
        struct InputHelper {
            FILE *m_file_ptr;
            char m_buf[INPUT_BUFFER_SIZE], *m_end, *m_cursor;
            bool m_ok;
            InputHelper &set_bad() { return m_ok = false, *this; }
            template <size_type BlockSize>
            void _reserve() {
                size_type a = m_end - m_cursor;
                if (a >= BlockSize) return;
                memmove(m_buf, m_cursor, a), m_cursor = m_buf;
                size_type b = a + fread(m_buf + a, 1, INPUT_BUFFER_SIZE - a, m_file_ptr);
                if (b < INPUT_BUFFER_SIZE) m_end = m_buf + b, *m_end = EOF;
            }
            template <typename Tp, typename BinaryOperation>
            InputHelper &fill_integer(Tp &ret, BinaryOperation op) {
                if (!isdigit(*m_cursor)) return set_bad();
                ret = op(Tp(0), *m_cursor - '0');
                size_type len = 1;
                while (isdigit(*(m_cursor + len))) ret = op(ret * 10, *(m_cursor + len++) - '0');
                m_cursor += len;
                return *this;
            }
            explicit InputHelper(const char *inputFileName) : m_ok(true), m_cursor(m_buf + INPUT_BUFFER_SIZE), m_end(m_buf + INPUT_BUFFER_SIZE) { m_file_ptr = *inputFileName ? fopen(inputFileName, "rt") : stdin; }
            ~InputHelper() { fclose(m_file_ptr); }
            static InputHelper &get_instance() {
                static InputHelper s_obj(input_file);
                return s_obj;
            }
            static bool is_blank(char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; }
            static bool is_endline(char c) { return c == '\n' || c == EOF; }
            const char &getchar_checked() {
                _reserve<1>();
                return *m_cursor;
            }
            const char &getchar_unchecked() const { return *m_cursor; }
            void next() { ++m_cursor; }
            template <typename Tp, typename std::enable_if<std::is_signed<Tp>::value & std::is_integral<Tp>::value>::type * = nullptr>
            InputHelper &operator>>(Tp &num) {
                while (is_blank(getchar_checked())) next();
                _reserve<MAX_INTEGER_SIZE>();
                if (getchar_unchecked() != '-') return fill_integer(num, std::plus<Tp>());
                next();
                return fill_integer(num, std::minus<Tp>());
            }
            template <typename Tp, typename std::enable_if<std::is_unsigned<Tp>::value & std::is_integral<Tp>::value>::type * = nullptr>
            InputHelper &operator>>(Tp &num) {
                while (is_blank(getchar_checked())) next();
                _reserve<MAX_INTEGER_SIZE>();
                return fill_integer(num, std::plus<Tp>());
            }
            template <typename Tp, typename std::enable_if<std::is_floating_point<Tp>::value>::type * = nullptr>
            InputHelper &operator>>(Tp &num) {
                bool neg = false, integer = false, decimal = false;
                while (is_blank(getchar_checked())) next();
                _reserve<MAX_FLOAT_SIZE>();
                if (getchar_unchecked() == '-') {
                    neg = true;
                    next();
                }
                if (!isdigit(getchar_unchecked()) && getchar_unchecked() != '.') return set_bad();
                if (isdigit(getchar_unchecked())) {
                    integer = true;
                    num = getchar_unchecked() - '0';
                    while (next(), isdigit(getchar_unchecked())) num = num * 10 + (getchar_unchecked() - '0');
                }
                if (getchar_unchecked() == '.')
                    if (next(), isdigit(getchar_unchecked())) {
                        if (!integer) num = 0;
                        decimal = true;
                        Tp unit = 0.1;
                        num += unit * (getchar_unchecked() - '0');
                        while (next(), isdigit(getchar_unchecked())) num += (unit *= 0.1) * (getchar_unchecked() - '0');
                    }
                if (!integer && !decimal) return set_bad();
                if (neg) num = -num;
                return *this;
            }
            InputHelper &operator>>(char &c) {
                while (is_blank(getchar_checked())) next();
                if (getchar_checked() == EOF) return set_bad();
                c = getchar_checked(), next();
                return *this;
            }
            InputHelper &operator>>(std::string &s) {
                while (is_blank(getchar_checked())) next();
                if (getchar_checked() == EOF) return set_bad();
                s.clear();
                do {
                    s += getchar_checked();
                    next();
                } while (!is_blank(getchar_checked()) && getchar_unchecked() != EOF);
                return *this;
            }
            explicit operator bool() { return m_ok; }
        };
        struct OutputHelper {
            FILE *m_file_ptr = nullptr;
            char m_buf[OUTPUT_BUFFER_SIZE], *m_end, *m_cursor;
            char m_temp_buf[MAX_FLOAT_SIZE], *m_temp_buf_cursor, *m_temp_buf_dot;
            uint64_t m_float_reserve, m_float_ratio;
            void _write() { fwrite(m_buf, 1, m_cursor - m_buf, m_file_ptr), m_cursor = m_buf; }
            template <size_type BlockSize>
            void _reserve() {
                size_type a = m_end - m_cursor;
                if (a >= BlockSize) return;
                _write();
            }
            OutputHelper(const char *outputFileName, size_type prec = 6) : m_cursor(m_buf), m_end(m_buf + OUTPUT_BUFFER_SIZE), m_temp_buf_cursor(m_temp_buf) { m_file_ptr = *outputFileName ? fopen(outputFileName, "wt") : stdout, precision(prec); }
            static OutputHelper &get_instance() {
                static OutputHelper s_obj(output_file);
                return s_obj;
            }
            ~OutputHelper() { flush(), fclose(m_file_ptr); }
            void precision(size_type prec) { m_float_reserve = prec, m_float_ratio = uint64_t(pow(10, prec)), m_temp_buf_dot = m_temp_buf + prec; }
            OutputHelper &flush() { return _write(), fflush(m_file_ptr), *this; }
            void putchar(const char &c) {
                if (m_cursor == m_end) _write();
                *m_cursor++ = c;
            }
            template <typename Tp, typename std::enable_if<std::is_signed<Tp>::value & std::is_integral<Tp>::value>::type * = nullptr>
            OutputHelper &operator<<(Tp ret) {
                _reserve<MAX_INTEGER_SIZE>();
                size_type len = 0;
                if (ret >= 0)
                    do *(m_cursor + len++) = '0' + ret % 10, ret /= 10;
                    while (ret);
                else {
                    putchar('-');
                    do *(m_cursor + len++) = '0' - ret % 10, ret /= 10;
                    while (ret);
                }
                for (size_type i = 0, j = len - 1; i < j;) std::swap(*(m_cursor + i++), *(m_cursor + j--));
                m_cursor += len;
                return *this;
            }
            template <typename Tp, typename std::enable_if<std::is_unsigned<Tp>::value & std::is_integral<Tp>::value>::type * = nullptr>
            OutputHelper &operator<<(Tp ret) {
                _reserve<MAX_INTEGER_SIZE>();
                size_type len = 0;
                do *(m_cursor + len++) = '0' + ret % 10, ret /= 10;
                while (ret);
                for (size_type i = 0, j = len - 1; i < j;) std::swap(*(m_cursor + i++), *(m_cursor + j--));
                m_cursor += len;
                return *this;
            }
            template <typename Tp, typename std::enable_if<std::is_floating_point<Tp>::value>::type * = nullptr>
            OutputHelper &operator<<(Tp ret) {
                if (ret < 0) {
                    putchar('-');
                    return *this << -ret;
                }
                ret *= m_float_ratio;
                uint64_t integer = ret;
                if (ret - integer >= 0.4999999999) integer++;
                do {
                    *m_temp_buf_cursor++ = '0' + integer % 10;
                    integer /= 10;
                } while (integer);
                if (m_temp_buf_cursor > m_temp_buf_dot) {
                    do putchar(*--m_temp_buf_cursor);
                    while (m_temp_buf_cursor > m_temp_buf_dot);
                    putchar('.');
                } else {
                    putchar('0'), putchar('.');
                    for (size_type i = m_temp_buf_dot - m_temp_buf_cursor; i--;) putchar('0');
                }
                do putchar(*--m_temp_buf_cursor);
                while (m_temp_buf_cursor > m_temp_buf);
                return *this;
            }
            OutputHelper &operator<<(const char &ret) {
                putchar(ret);
                return *this;
            }
            OutputHelper &operator<<(const char *ret) {
                while (*ret) putchar(*ret++);
                return *this;
            }
            OutputHelper &operator<<(const std::string &ret) { return *this << ret.data(); }
        };
        InputHelper &getline(InputHelper &ih, std::string &line) {
            line.clear();
            if (ih.getchar_checked() == EOF) return ih.set_bad();
            while (!InputHelper::is_endline(ih.getchar_checked())) line += ih.getchar_unchecked(), ih.next();
            if (ih.getchar_unchecked() != EOF) ih.next();
            return ih;
        }
    }
}
using OY::IO::getline;
#endif 
#ifndef __OY_SIFTHEAP__
#define __OY_SIFTHEAP__
namespace OY {
    namespace Sift {
        using size_type = uint32_t;
        template <typename Sequence>
        struct Getter;
        template <typename Tp>
        struct Getter<std::vector<Tp>> {
            std::vector<Tp> &m_sequence;
            Getter(std::vector<Tp> &sequence) : m_sequence(sequence) {}
            const Tp &operator()(size_type index) const { return m_sequence[index]; }
        };
        template <typename Tp>
        struct Getter<Tp *> {
            Tp *m_sequence;
            Getter(Tp *sequence) : m_sequence(sequence) {}
            const Tp &operator()(size_type index) const { return *(m_sequence + index); }
        };
        template <typename Mapping, typename Compare = std::less<void>, size_type MAX_NODE = 1 << 20>
        struct Heap {
            static size_type s_buffer[MAX_NODE << 1], s_use_count;
            size_type *m_heap, *m_pos, m_size;
            Mapping m_map;
            Compare m_comp;
            Heap(size_type length, Mapping map, Compare comp = Compare()) : m_map(map), m_comp(comp) { resize(length); }
            void resize(size_type length) {
                m_heap = s_buffer + s_use_count, m_pos = s_buffer + s_use_count + length, m_size = 0, s_use_count += length << 1;
                std::fill_n(m_pos, length, -1);
            }
            void sift_up(size_type i) {
                size_type curpos = m_pos[i], p;
                auto &&curvalue = m_map(i);
                for (; curpos; curpos = (curpos - 1) >> 1) {
                    if (!m_comp(m_map(p = m_heap[(curpos - 1) >> 1]), curvalue)) break;
                    m_heap[m_pos[p] = curpos] = p;
                }
                m_heap[m_pos[i] = curpos] = i;
            }
            void sift_down(size_type i) {
                size_type curpos = m_pos[i], c;
                auto &&curvalue = m_map(i);
                for (; (c = curpos * 2 + 1) < m_size; curpos = c) {
                    if (c + 1 < m_size && m_comp(m_map(m_heap[c]), m_map(m_heap[c + 1]))) c++;
                    if (!m_comp(curvalue, m_map(m_heap[c]))) break;
                    m_pos[m_heap[curpos] = m_heap[c]] = curpos;
                }
                m_heap[m_pos[i] = curpos] = i;
            }
            void clear() {
                for (size_type i = 0; i != m_size; i++) m_pos[i] = -1;
                m_size = 0;
            }
            void push(size_type i) {
                if (!~m_pos[i]) {
                    m_pos[i] = m_size;
                    m_heap[m_size++] = i;
                }
                sift_up(i);
            }
            size_type top() const { return m_heap[0]; }
            void pop() {
                m_pos[m_heap[0]] = -1;
                if (--m_size) {
                    m_pos[m_heap[m_size]] = 0;
                    m_heap[0] = m_heap[m_size];
                    sift_down(m_heap[0]);
                }
            }
            bool empty() const { return !m_size; }
            size_type size() const { return m_size; }
        };
        template <typename Mapping, typename Compare, size_type MAX_NODE>
        size_type Heap<Mapping, Compare, MAX_NODE>::s_buffer[MAX_NODE << 1];
        template <typename Mapping, typename Compare, size_type MAX_NODE>
        size_type Heap<Mapping, Compare, MAX_NODE>::s_use_count;
    }
    template <typename Tp, typename Compare = std::less<Tp>, Sift::size_type MAX_NODE = 1 << 20, typename HeapType = Sift::Heap<Sift::Getter<std::vector<Tp>>, Compare, MAX_NODE>>
    auto make_SiftHeap(Sift::size_type length, std::vector<Tp> &items, Compare comp = Compare()) -> HeapType { return HeapType(length, Sift::Getter<std::vector<Tp>>(items), comp); }
    template <typename Tp, typename Compare = std::less<Tp>, Sift::size_type MAX_NODE = 1 << 20, typename HeapType = Sift::Heap<Sift::Getter<Tp *>, Compare, MAX_NODE>>
    auto make_SiftHeap(Sift::size_type length, Tp *items, Compare comp = Compare()) -> HeapType { return HeapType(length, Sift::Getter<Tp *>(items), comp); }
    template <typename Sequence>
    using SiftGetter = Sift::Getter<Sequence>;
    template <typename Mapping, typename Compare = std::less<void>, Sift::size_type MAX_NODE = 1 << 20>
    using SiftHeap = Sift::Heap<Mapping, Compare, MAX_NODE>;
}
#endif

struct dsu {
	dsu(int n) {
		p.resize(n, -1);
		pp.resize(n); for (int i = 0; i < n; i++) pp[i] = i;
		r.resize(n, 0);
	}
	inline int par(int x) {
		return pp[_par(x)];
	}
	inline int _par(int x) {
		return p[x] == -1 ? x : p[x] = _par(p[x]);
	}
	inline void merge(int a, int b) {
		a = _par(a); b = _par(b);
		if (a == b)return;
		if (r[a] < r[b]) {
			swap(a, b);
			swap(pp[a], pp[b]);
		}
		if (r[a] == r[b]) r[a]++;
		p[b] = a;
	}
	vector<int> p, r, pp;
};
 
signed main() {
  // ios_base::sync_with_stdio(false); cin.tie(NULL);
	int N, D, T; cin >> N >> D >> T;
	vector<int> t(N); for (auto& x : t) cin >> x;
	int l = 0, r = 2e6, m = 0;
	int ans = 0;
	while (l < r) {//aliens HAHAHAhaha ha ha :sob:
		m = (l + r) / 2;
		vector<pair<int,int>> st; st.reserve(N);
		struct node {
			int p = -1;//prev
			int n = -1;//next
			int lz = 0;
			int v = 0;
			int c = 0; // count owo!!!
			node() {};
			node(int v, int c) : v(v), c(c) {};
		};
		vector<node> st2; st2.reserve(N);
		dsu pls(N);
		int start = 0; 
		int amt = 0;//amount added
		function<void(int)> kill = [&](int i) {
			int n = st2[i].n;
			//assert(n != -1); 
			if (n == -1) return;
			if ((st2[i].v + (int)st2[i].lz > st2[n].v)) {
				int p = st2[i].p;
				st2[n].p = p;
				if (p != -1) {
					st2[p].lz += st2[i].lz;
					st2[p].n = n;
					pls.merge(p, i); //merge i to p
					kill(p);
				}
				else {
					// DEAD
					amt -= st2[i].lz; //recycle owo
					start = n;
				}
			}
		};
		for (int i = 0; i < N; i++) {
			//create and then upd
			if (st2.size()) {
				st2.push_back(node(st2[start].v + (int)amt + m, st2[start].c+1));
				st2[i - 1].n = i; st2[i].p = i - 1;
				kill(i - 1);
			}
			else {
				st2.push_back(node());
			}
 
			int o = i;
			if (t[i] <= T) {
				while (st.size() && st.back().ff >= t[i] - i) {
					st.pop_back();
				}
				st.push_back({ t[i] - i, i});
			}
			else {
				while (st.size() && st.back().ff > T - i) st.pop_back();
				if (st.size()) {
					o = st.back().ss;
				}
				else o = -1;
			}
			//cout << o << ",";
			if(o >= start){
				int t = pls.par(o);
				st2[t].lz++; amt++;
				kill(t);
			}
			//cout << amt << ",";
		}
		//cout << endl;
		int c = st2[start].c;
		//cout << c << endl;
		if (c <= D) {
			r = m;
			ans = round((int)st2[start].v + (int)amt - (int)D * m);
		}
		else {
			//cout << "fuck" << endl;
			l = m + 1;
		}
	}
	cout << ans << endl;
	// n log n inverse ackermann n please pass i swear to god
}

컴파일 시 표준 에러 (stderr) 메시지

prison.cpp: In constructor 'OY::IO::InputHelper::InputHelper(const char*)':
prison.cpp:44:18: warning: 'OY::IO::InputHelper::m_ok' will be initialized after [-Wreorder]
   44 |             bool m_ok;
      |                  ^~~~
prison.cpp:43:53: warning:   'char* OY::IO::InputHelper::m_cursor' [-Wreorder]
   43 |             char m_buf[INPUT_BUFFER_SIZE], *m_end, *m_cursor;
      |                                                     ^~~~~~~~
prison.cpp:63:22: warning:   when initialized here [-Wreorder]
   63 |             explicit InputHelper(const char *inputFileName) : m_ok(true), m_cursor(m_buf + INPUT_BUFFER_SIZE), m_end(m_buf + INPUT_BUFFER_SIZE) { m_file_ptr = *inputFileName ? fopen(inputFileName, "rt") : stdin; }
      |                      ^~~~~~~~~~~
prison.cpp:43:53: warning: 'OY::IO::InputHelper::m_cursor' will be initialized after [-Wreorder]
   43 |             char m_buf[INPUT_BUFFER_SIZE], *m_end, *m_cursor;
      |                                                     ^~~~~~~~
prison.cpp:43:45: warning:   'char* OY::IO::InputHelper::m_end' [-Wreorder]
   43 |             char m_buf[INPUT_BUFFER_SIZE], *m_end, *m_cursor;
      |                                             ^~~~~
prison.cpp:63:22: warning:   when initialized here [-Wreorder]
   63 |             explicit InputHelper(const char *inputFileName) : m_ok(true), m_cursor(m_buf + INPUT_BUFFER_SIZE), m_end(m_buf + INPUT_BUFFER_SIZE) { m_file_ptr = *inputFileName ? fopen(inputFileName, "rt") : stdin; }
      |                      ^~~~~~~~~~~
prison.cpp: In constructor 'OY::IO::OutputHelper::OutputHelper(const char*, OY::IO::size_type)':
prison.cpp:138:54: warning: 'OY::IO::OutputHelper::m_cursor' will be initialized after [-Wreorder]
  138 |             char m_buf[OUTPUT_BUFFER_SIZE], *m_end, *m_cursor;
      |                                                      ^~~~~~~~
prison.cpp:138:46: warning:   'char* OY::IO::OutputHelper::m_end' [-Wreorder]
  138 |             char m_buf[OUTPUT_BUFFER_SIZE], *m_end, *m_cursor;
      |                                              ^~~~~
prison.cpp:148:13: warning:   when initialized here [-Wreorder]
  148 |             OutputHelper(const char *outputFileName, size_type prec = 6) : m_cursor(m_buf), m_end(m_buf + OUTPUT_BUFFER_SIZE), m_temp_buf_cursor(m_temp_buf) { m_file_ptr = *outputFileName ? fopen(outputFileName, "wt") : stdout, precision(prec); }
      |             ^~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...