結果
| 問題 |
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;
}
noshi91