結果
問題 | No.738 平らな農地 |
ユーザー | fine |
提出日時 | 2020-06-04 02:34:12 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 261 ms / 2,000 ms |
コード長 | 12,882 bytes |
コンパイル時間 | 2,915 ms |
コンパイル使用メモリ | 198,988 KB |
実行使用メモリ | 9,856 KB |
最終ジャッジ日時 | 2024-05-05 10:14:58 |
合計ジャッジ時間 | 15,815 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 5 ms
5,376 KB |
testcase_06 | AC | 6 ms
5,376 KB |
testcase_07 | AC | 7 ms
5,376 KB |
testcase_08 | AC | 4 ms
5,376 KB |
testcase_09 | AC | 3 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 3 ms
5,376 KB |
testcase_12 | AC | 3 ms
5,376 KB |
testcase_13 | AC | 5 ms
5,376 KB |
testcase_14 | AC | 3 ms
5,376 KB |
testcase_15 | AC | 228 ms
5,888 KB |
testcase_16 | AC | 222 ms
6,272 KB |
testcase_17 | AC | 236 ms
5,376 KB |
testcase_18 | AC | 237 ms
5,376 KB |
testcase_19 | AC | 176 ms
5,376 KB |
testcase_20 | AC | 225 ms
6,016 KB |
testcase_21 | AC | 242 ms
5,376 KB |
testcase_22 | AC | 239 ms
5,760 KB |
testcase_23 | AC | 232 ms
5,376 KB |
testcase_24 | AC | 217 ms
5,376 KB |
testcase_25 | AC | 3 ms
5,376 KB |
testcase_26 | AC | 3 ms
5,376 KB |
testcase_27 | AC | 3 ms
5,376 KB |
testcase_28 | AC | 3 ms
5,376 KB |
testcase_29 | AC | 3 ms
5,376 KB |
testcase_30 | AC | 3 ms
5,376 KB |
testcase_31 | AC | 3 ms
5,376 KB |
testcase_32 | AC | 2 ms
5,376 KB |
testcase_33 | AC | 3 ms
5,376 KB |
testcase_34 | AC | 2 ms
5,376 KB |
testcase_35 | AC | 2 ms
5,376 KB |
testcase_36 | AC | 3 ms
5,376 KB |
testcase_37 | AC | 3 ms
5,376 KB |
testcase_38 | AC | 2 ms
5,376 KB |
testcase_39 | AC | 3 ms
5,376 KB |
testcase_40 | AC | 3 ms
5,376 KB |
testcase_41 | AC | 3 ms
5,376 KB |
testcase_42 | AC | 2 ms
5,376 KB |
testcase_43 | AC | 3 ms
5,376 KB |
testcase_44 | AC | 3 ms
5,376 KB |
testcase_45 | AC | 239 ms
7,168 KB |
testcase_46 | AC | 239 ms
6,272 KB |
testcase_47 | AC | 261 ms
7,040 KB |
testcase_48 | AC | 205 ms
7,168 KB |
testcase_49 | AC | 210 ms
7,168 KB |
testcase_50 | AC | 214 ms
7,552 KB |
testcase_51 | AC | 246 ms
6,528 KB |
testcase_52 | AC | 217 ms
6,656 KB |
testcase_53 | AC | 231 ms
6,656 KB |
testcase_54 | AC | 242 ms
6,784 KB |
testcase_55 | AC | 241 ms
6,400 KB |
testcase_56 | AC | 237 ms
6,528 KB |
testcase_57 | AC | 233 ms
6,528 KB |
testcase_58 | AC | 219 ms
6,912 KB |
testcase_59 | AC | 234 ms
7,424 KB |
testcase_60 | AC | 220 ms
7,552 KB |
testcase_61 | AC | 214 ms
7,296 KB |
testcase_62 | AC | 212 ms
6,912 KB |
testcase_63 | AC | 238 ms
6,656 KB |
testcase_64 | AC | 221 ms
6,912 KB |
testcase_65 | AC | 23 ms
5,376 KB |
testcase_66 | AC | 24 ms
5,376 KB |
testcase_67 | AC | 101 ms
6,528 KB |
testcase_68 | AC | 103 ms
6,912 KB |
testcase_69 | AC | 144 ms
5,376 KB |
testcase_70 | AC | 126 ms
6,272 KB |
testcase_71 | AC | 110 ms
5,376 KB |
testcase_72 | AC | 118 ms
5,376 KB |
testcase_73 | AC | 80 ms
6,272 KB |
testcase_74 | AC | 130 ms
5,376 KB |
testcase_75 | AC | 134 ms
5,376 KB |
testcase_76 | AC | 129 ms
6,272 KB |
testcase_77 | AC | 129 ms
5,376 KB |
testcase_78 | AC | 136 ms
5,376 KB |
testcase_79 | AC | 176 ms
5,376 KB |
testcase_80 | AC | 157 ms
5,888 KB |
testcase_81 | AC | 167 ms
5,376 KB |
testcase_82 | AC | 163 ms
5,376 KB |
testcase_83 | AC | 107 ms
5,376 KB |
testcase_84 | AC | 124 ms
5,376 KB |
testcase_85 | AC | 35 ms
5,376 KB |
testcase_86 | AC | 39 ms
5,376 KB |
testcase_87 | AC | 129 ms
9,856 KB |
testcase_88 | AC | 122 ms
9,600 KB |
testcase_89 | AC | 1 ms
5,376 KB |
testcase_90 | AC | 2 ms
5,376 KB |
testcase_91 | AC | 2 ms
5,376 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; constexpr char newl = '\n'; template<class U = ll, class V = U> struct Nothing { using Tm = U; using To = V; static Tm merge(const Tm& x, const Tm& y) { return unit(); } static To op_merge(const To& x, const To& y) { return op_unit(); } static Tm apply(const Tm& vm, const To& vo, size_t seg_len) { return vm; } static constexpr Tm unit() { return Tm(0); } static constexpr To op_unit() { return To(0); } }; // https://www.slideshare.net/iwiwi/2-12188757 // https://tubo28.me/compprog/algorithm/treap/ // https://ei1333.github.io/luzhiled/snippets/structure/rbst.html // https://qiita.com/tubo28/items/f058582e457f6870a800 template <class MonoidOp = Nothing<> > class Treap { public: using Tm = typename MonoidOp::Tm; using To = typename MonoidOp::To; private: inline static unsigned int randxor() noexcept { static unsigned int x=123456789,y=362436069,z=521288629,w=88675123; unsigned int t; t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) ); } public: struct Node { unsigned int pri; size_t sz; Tm val, sum; To lazy; unique_ptr<Node> lch, rch; Node(const Tm& x) : pri(randxor()), sz(1), val(x), sum(x), lazy(MonoidOp::op_unit()) {} static constexpr size_t size(const unique_ptr<Node>& node) noexcept { return (!node ? 0 : node->sz); } static constexpr Tm getSum(const unique_ptr<Node>& node) noexcept { return (!node ? MonoidOp::unit() : node->sum); } }; private: inline static unique_ptr<Node>& update(unique_ptr<Node>& node) noexcept { node->sz = Node::size(node->lch) + Node::size(node->rch) + 1; node->sum = MonoidOp::merge(MonoidOp::merge(Node::getSum(node->lch), node->val), Node::getSum(node->rch)); return node; } inline static unique_ptr<Node>& push(unique_ptr<Node>& node) noexcept { if (node->lazy == MonoidOp::op_unit()) return update(node); node->val = MonoidOp::apply(node->val, node->lazy, 1); if (node->lch) { node->lch->lazy = MonoidOp::op_merge(node->lch->lazy, node->lazy); node->lch->sum = MonoidOp::apply(node->lch->sum, node->lazy, Node::size(node->lch)); } if (node->rch) { node->rch->lazy = MonoidOp::op_merge(node->rch->lazy, node->lazy); node->rch->sum = MonoidOp::apply(node->rch->sum, node->lazy, Node::size(node->rch)); } node->lazy = MonoidOp::op_unit(); return update(node); } // split into [0, pos), [pos, size(node)) static pair< unique_ptr<Node>, unique_ptr<Node> > split(unique_ptr<Node> node, size_t pos) noexcept { if (!node) return pair< unique_ptr<Node>, unique_ptr<Node> >(); assert(pos <= Node::size(node)); push(node); if (pos <= Node::size(node->lch)) { auto p = split(move(node->lch), pos); node->lch = move(p.second); return {move(p.first), move(update(node))}; } else { auto p = split(move(node->rch), pos - Node::size(node->lch) - 1); node->rch = move(p.first); return {move(update(node)), move(p.second)}; } } static unique_ptr<Node> merge(unique_ptr<Node> nodeL, unique_ptr<Node> nodeR) noexcept { if (!nodeR) return nodeL; if (!nodeL) return nodeR; if (nodeL->pri > nodeR->pri) { push(nodeL); nodeL->rch = merge(move(nodeL->rch), move(nodeR)); return move(update(nodeL)); } else { push(nodeR); nodeR->lch = merge(move(nodeL), move(nodeR->lch)); return move(update(nodeR)); } } static void insert(unique_ptr<Node>& node, size_t pos, const Tm& val) noexcept { auto p = split(move(node), pos); auto tmp = merge(move(p.first), move(unique_ptr<Node>(new Node(val)))); node = move(merge(move(tmp), move(p.second))); } static void erase(unique_ptr<Node>& node, size_t pos) noexcept { if (!node) return; assert(pos < Node::size(node)); auto pr = split(move(node), pos + 1); auto pl = split(move(pr.first), pos); node = merge(move(pl.first), move(pr.second)); } static void update(unique_ptr<Node>& node, size_t a, size_t b, const To& x) noexcept { auto p1 = split(move(node), b); auto p2 = split(move(p1.first), a); p2.second->lazy = MonoidOp::op_merge(p2.second->lazy, x); node = merge(merge(move(p2.first), move(push(p2.second))), move(p1.second)); } static Tm query(unique_ptr<Node>& node, size_t a, size_t b) noexcept { auto p1 = split(move(node), b); auto p2 = split(move(p1.first), a); Tm res = Node::getSum(p2.second); node = merge(merge(move(p2.first), move(p2.second)), move(p1.second)); return res; } static void set(unique_ptr<Node>& node, size_t pos, const Tm& x) { push(node); if (pos < Node::size(node->lch)) set(node->lch, pos, x); else if (pos == Node::size(node->lch)) node->val = x; else set(node->rch, pos - Node::size(node->lch) - 1, x); update(node); } static unique_ptr<Node> build(size_t l, size_t r, const vector<Tm>& v) { if (l + 1 >= r) return unique_ptr<Node>(new Node(v[l])); return merge(build(l, (l + r) >> 1, v), build((l + r) >> 1, r, v)); } static void dump(unique_ptr<Node>& node) noexcept { if (!node) return; push(node); dump(node->lch); cerr << node->val << " "; dump(node->rch); } public: unique_ptr<Node> root; public: Treap(unique_ptr<Node>& node) : root(move(node)) {} public: Treap() = default; Treap(size_t sz, const Tm& initial_value = MonoidOp::unit()) { vector<Tm> v(sz, initial_value); root = build(0, sz, v); } Treap(const vector<Tm>& v) { root = build(0, v.size(), v); } constexpr bool empty() const noexcept { return !root; } constexpr size_t size() const noexcept { return Node::size(root); } // // split into [0, pos), [pos, size()) // [WARNING!!!]: Don't use this Treap after split inline pair< Treap, Treap > split(size_t pos) noexcept { auto p = split(move(root), pos); return {Treap(p.first), Treap(p.second)}; } // merge tree from the right of this Treap // [WARNING!!!]: Don't use tree after merge inline void merge(Treap& tree) noexcept { root = merge(move(root), move(tree.root)); } inline void insert_at(size_t pos, const Tm& val) noexcept { insert(root, pos, val); } inline void erase_at(size_t pos) noexcept { erase(root, pos); } // [a, b) inline void update(size_t a, size_t b, const To& x) { update(root, a, b, x); } // [a, b) inline Tm query(size_t a, size_t b) noexcept { return query(root, a, b); } inline Tm get(size_t pos) noexcept { return query(pos, pos + 1); } inline void set(size_t pos, const Tm& x) { set(root, pos, x); } inline void dump() noexcept { cerr << "Seq: "; dump(root); cerr << newl; } }; // 以下、MonoidOpの例 template<class U = ll, class V = U> struct RangeSumAdd { using Tm = U; using To = V; static Tm merge(Tm x, Tm y) { return x + y; } static To op_merge(To x, To y) { return x + y; } static Tm apply(Tm vm, To vo, int seg_len) { return vm + vo * seg_len; } static constexpr Tm unit() { return Tm(0); } static constexpr To op_unit() { return To(0); } }; template<class U = ll, class V = U> struct RangeMinUpdate { using Tm = U; using To = V; static Tm merge(Tm x, Tm y) { return min(x, y); } static To op_merge(To x, To y) { return y; } static Tm apply(Tm vm, To vo, int seg_len) { return vo == op_unit() ? vm : vo; } static constexpr Tm unit() { return numeric_limits<Tm>::max(); } static constexpr To op_unit() { return numeric_limits<To>::max(); } }; // 作用素の初期値は更新クエリで与えられる値の定義域の範囲外の値にする template<class U = ll, class V = U> struct RangeSumUpdate { using Tm = U; using To = V; static Tm merge(Tm x, Tm y) { return x + y; } static To op_merge(To x, To y) { return y; } static Tm apply(Tm vm, To vo, int seg_len) { return vo == op_unit() ? vm : vo * seg_len; } static constexpr Tm unit() { return Tm(0); } static constexpr To op_unit() { return numeric_limits<To>::min(); } }; // 初期値 != 単位元 の場合に注意 template<class U = ll, class V = U> struct RangeMinAdd { using Tm = U; using To = V; static Tm merge(Tm x, Tm y) { return min(x, y); } static To op_merge(To x, To y) { return x + y; } static Tm apply(Tm vm, To vo, int seg_len) { return vm + vo; } static constexpr Tm unit() { return numeric_limits<Tm>::max(); } static constexpr To op_unit() { return To(0); } }; // [Depends on]: Treap template<class T> class OrderedMultiSet : public Treap< RangeSumAdd<T> > { public: using Tree = Treap< RangeSumAdd<T> >; using Node = typename Tree::Node; private: static T at(const unique_ptr<Node>& node, size_t pos) noexcept { if (pos < Node::size(node->lch)) return at(node->lch, pos); if (pos == Node::size(node->lch)) return node->val; return at(node->rch, pos - Node::size(node->lch) - 1); } static size_t lower_bound(const unique_ptr<Node>& node, T val) noexcept { if (!node) return 0; if (val <= node->val) return lower_bound(node->lch, val); return lower_bound(node->rch, val) + Node::size(node->lch) + 1; } static size_t upper_bound(const unique_ptr<Node>& node, T val) noexcept { if (!node) return 0; if (val < node->val) return upper_bound(node->lch, val); return upper_bound(node->rch, val) + Node::size(node->lch) + 1; } static bool contains(const unique_ptr<Node>& node, T val) noexcept { if (!node) return false; if (val == node->val) return true; if (val < node->val) return contains(node->lch, val); else return contains(node->rch, val); } // Use these function only inside void insert_at(size_t, const typename Tree::Tm&); void erase_at(size_t); public: using Tree::Treap; // Note: https://qiita.com/matsumoto_sp/items/233503b4a31dc1f190b6 OrderedMultiSet() = default; OrderedMultiSet(Tree& t) : OrderedMultiSet(t.root) {} OrderedMultiSet(const vector<T>& v) : Tree::Treap(v) { assert(is_sorted(v.begin(), v.end())); } // Don't use these functions //void update(size_t, size_t, const typename Tree::To&) = delete; //typename Tree::Tm query(size_t, size_t, const typename Tree::To&) = delete; //typename Tree::Tm get(size_t) = delete; //void set(size_t, const typename Tree::Tm&) = delete; inline T at(size_t pos) noexcept { assert(pos < Tree::size()); return at(Tree::root, pos); } // return position (index) // if val doesn't exist, return size() inline size_t find(T val) noexcept { return (contains(val) ? lower_bound(val) : Tree::size()); } // return position (index) inline size_t lower_bound(T val) noexcept { return lower_bound(Tree::root, val); } // return position (index) inline size_t upper_bound(T val) noexcept { return upper_bound(Tree::root, val); } inline bool contains(T val) noexcept { return contains(Tree::root, val); } inline size_t count(T val) noexcept { return upper_bound(val) - lower_bound(val); } inline virtual void insert(T val) noexcept { Tree::insert_at(lower_bound(val), val); } inline void erase(T val) noexcept { if (!contains(val)) return; Tree::erase_at(lower_bound(val)); } }; int main() { cin.tie(nullptr); ios::sync_with_stdio(false); int q, K; cin >> q >> K; vector<ll> a(q); for (int i = 0; i < q; i++) { cin >> a[i]; } OrderedMultiSet<ll> s; ll ans = 1e18; for (int i = 0; i < q; i++) { if (i >= K) { s.erase(a[i - K]); } s.insert(a[i]); if (s.size() == K) { ll tar = s.at(K / 2); auto p = s.split(K / 2); ll sz1 = p.first.size(), sz2 = p.second.size(); ans = min(ans, tar * sz1 - p.first.query(0, sz1) + p.second.query(0, sz2) - tar * sz2); p.first.merge(p.second); s = OrderedMultiSet<ll>(p.first); } } cout << ans << newl; return 0; }