結果
問題 | No.925 紲星 Extra |
ユーザー | noshi91 |
提出日時 | 2019-11-08 22:37:21 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 8,696 ms / 10,000 ms |
コード長 | 5,978 bytes |
コンパイル時間 | 2,021 ms |
コンパイル使用メモリ | 116,532 KB |
実行使用メモリ | 263,296 KB |
最終ジャッジ日時 | 2024-09-15 01:51:59 |
合計ジャッジ時間 | 82,441 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 19 |
ソースコード
/* 限度さん... */ #include <cstddef> #include <cstdint> #include <memory> #include <utility> using usize = std::size_t; using u64 = std::uint_fast64_t; class treap { public: using size_type = std::size_t; private: static u64 xorshift() { static u64 seed = 91; seed ^= seed << 7; seed ^= seed >> 9; return seed; } class node_type; using pointer = std::unique_ptr<node_type>; class node_type { friend treap; pointer left; pointer right; size_type size; u64 priority; usize key; u64 val; u64 sum; public: node_type(const usize key, const u64 val) : left(), right(), size(1), priority(xorshift()), key(key), val(val), sum(val) {} }; static size_type size(const pointer &ptr) { return ptr ? ptr->size : 0; } static u64 sum(const pointer &ptr) { return ptr ? ptr->sum : 0; } static u64 priority(const pointer &ptr) { return ptr ? ptr->priority : 0; } static void fix(const pointer &ptr) { ptr->size = size(ptr->left) + 1 + size(ptr->right); ptr->sum = sum(ptr->left) + ptr->val + sum(ptr->right); } static void rotate_left(pointer &ptr) { pointer right = std::move(ptr->right); ptr->right = std::move(right->left); fix(ptr); right->left = std::move(ptr); fix(right); ptr = std::move(right); } static void rotate_right(pointer &ptr) { pointer left = std::move(ptr->left); ptr->left = std::move(left->right); fix(ptr); left->right = std::move(ptr); fix(left); ptr = std::move(left); } static void insert(pointer &ptr, const usize key, const u64 val) { if (!ptr) { ptr = std::make_unique<node_type>(key, val); return; } if (key == ptr->key) { return; } if (key < ptr->key) { insert(ptr->left, key, val); fix(ptr); if (ptr->left->priority > ptr->priority) { rotate_right(ptr); } } else { insert(ptr->right, key, val); fix(ptr); if (ptr->right->priority > ptr->priority) { rotate_left(ptr); } } } static void erase(pointer &ptr, const usize key) { if (!ptr) { return; } if (key == ptr->key) { if (!ptr->left && !ptr->right) { ptr.reset(); return; } if (priority(ptr->left) > priority(ptr->right)) { rotate_right(ptr); } else { rotate_left(ptr); } } if (key < ptr->key) { erase(ptr->left, key); fix(ptr); } else { erase(ptr->right, key); fix(ptr); } } static usize count(const pointer &ptr, const size_type key) { if (!ptr) { return 0; } if (key <= ptr->key) { return count(ptr->left, key); } else { return size(ptr->left) + 1 + count(ptr->right, key); } } static u64 fold(const pointer &ptr, const usize key) { if (!ptr) { return 0; } if (key <= ptr->key) { return fold(ptr->left, key); } else { return sum(ptr->left) + ptr->val + fold(ptr->right, key); } } pointer root; public: treap() : root() {} void insert_(const usize key, const u64 val) { insert(root, key, val); } void erase_(const usize key) { erase(root, key); } usize count_(const usize l, const usize r) { return count(root, r) - count(root, l); } u64 fold_(const usize l, const usize r) { return fold(root, r) - fold(root, l); } }; struct kizuna { struct base; using base_ptr = std::unique_ptr<base>; struct base { base_ptr left, right; treap tree; }; base_ptr root; void erase(u64 pos, usize pos2) { base *ptr = root.get(); usize p = 40; while (p != 0) { p -= 1; ptr->tree.erase_(pos2); if (pos >> p & 1) { ptr = ptr->right.get(); } else { ptr = ptr->left.get(); } } ptr->tree.erase_(pos2); } void insert(u64 pos, usize pos2) { if (!root) { root = std::make_unique<base>(); } base *ptr = root.get(); ptr->tree.insert_(pos2, pos); usize p = 40; while (p != 0) { p -= 1; if (pos >> p & 1) { if (!ptr->right) { ptr->right = std::make_unique<base>(); } ptr = ptr->right.get(); } else { if (!ptr->left) { ptr->left = std::make_unique<base>(); } ptr = ptr->left.get(); } ptr->tree.insert_(pos2, pos); } } u64 score(const usize l, const usize r) { const usize mid_c = (r - l) / 2; usize mid = mid_c; u64 less = 0, greater = 0; u64 sep = 0; base *ptr = root.get(); usize p = 40; while (p != 0) { p -= 1; const usize count = ptr->left ? ptr->left->tree.count_(l, r) : 0; if (mid >= count) { mid -= count; less += ptr->left ? ptr->left->tree.fold_(l, r) : 0; ptr = ptr->right.get(); sep |= u64(1) << p; } else { greater += ptr->right ? ptr->right->tree.fold_(l, r) : 0; ptr = ptr->left.get(); } } const usize lc = mid_c - mid; const usize gc = r - l - lc - ptr->tree.count_(l, r); return sep * lc - less + greater - sep * gc; } }; #include <iostream> #include <vector> int main() { int n, q; std::cin >> n >> q; kizuna kiz; std::vector<u64> a(n); for (int i = 0; i < n; ++i) { std::cin >> a[i]; kiz.insert(a[i], i); } u64 acc = 0; for (int i = 0; i < q; ++i) { int t; std::cin >> t; if (t == 1) { u64 x, y; std::cin >> x >> y; x = x ^ acc % (u64(1) << 16); y = y ^ acc % (u64(1) << 40); x -= 1; kiz.erase(a[x], x); a[x] = y; kiz.insert(a[x], x); } else { u64 l, r; std::cin >> l >> r; l = l ^ acc % (u64(1) << 16); r = r ^ acc % (u64(1) << 16); if (l > r) { std::swap(l, r); } l -= 1; const u64 ans = kiz.score(l, r); std::cout << ans << std::endl; acc ^= ans; } } return 0; }