Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _CRT_SECURE_NO_WARNINGS
- #include <assert.h>
- #include <algorithm>
- #include <array>
- #include <string_view>
- #include <bitset>
- #include <chrono>
- #include <fstream>
- #include <functional>
- #include <iomanip>
- #include <variant>
- #include <iostream>
- #include <map>
- #include <numeric>
- #include <optional>
- #include <queue>
- #include <random>
- #include <set>
- #include <sstream>
- #include <string>
- #include <thread>
- #include <unordered_map>
- #include <unordered_set>
- #include <variant>
- #include <vector>
- using namespace std;
- const int MAXN = 3e6;
- struct /*__attribute__((__packed__))*/ node {
- int l, r, sz;
- uint32_t rk;
- char lit;
- };
- mt19937 gen(345678);
- node nodes[MAXN];
- int cid = 0;
- int next() {
- int r = ++cid;
- if (r == MAXN) exit(-1);
- nodes[r].rk = gen();
- return r;
- }
- void upd(int v) {
- if (!v) return;
- nodes[v].sz = 1 + (nodes[v].l ? nodes[nodes[v].l].sz : 0) +
- (nodes[v].r ? nodes[nodes[v].r].sz : 0);
- }
- inline int cnt(int v) {
- if (!v) return 0;
- return nodes[v].sz;
- }
- int merge(int l, int r) {
- if (!l) return r;
- if (!r) return l;
- if (nodes[l].rk > nodes[r].rk) {
- nodes[l].r = merge(nodes[l].r, r);
- upd(l);
- return l;
- }
- else {
- nodes[r].l = merge(l, nodes[r].l);
- upd(r);
- return r;
- }
- }
- pair<int, int> split(int p, int x) {
- if (!p) return { 0, 0 };
- if (cnt(nodes[p].l) < x) {
- auto [l, r] = split(nodes[p].r, x - cnt(nodes[p].l) - 1);
- nodes[p].r = l;
- upd(p);
- return { p, r };
- }
- else {
- auto [l, r] = split(nodes[p].l, x);
- nodes[p].l = r;
- upd(p);
- return { l, p };
- }
- }
- void append(int& t, int it) { t = merge(t, it); }
- int insert(const string& l, const string& r) {
- int ll = 0, rr = 0;
- if (l.size() == 1) {
- ll = next();
- nodes[ll].sz = 1;
- nodes[ll].lit = l[0];
- }
- if (r.size() == 1) {
- rr = next();
- nodes[rr].sz = 1;
- nodes[rr].lit = r[0];
- }
- if (!ll && !rr) return merge(insert(l.substr(0, l.size() / 2), l.substr(l.size() / 2)), insert(r.substr(0, r.size() / 2), r.substr(r.size() / 2)));
- if (!rr && r.size()) return merge(ll, insert(r.substr(0, r.size() / 2), r.substr(r.size() / 2)));
- if (!ll && l.size()) return merge(insert(l.substr(0, l.size() / 2), l.substr(l.size() / 2)), rr);
- return merge(ll, rr);
- }
- void print(stringstream& s, int t) {
- if (!t) return;
- print(s, nodes[t].l);
- s << nodes[t].lit;
- print(s, nodes[t].r);
- }
- void print(string& s, int t) {
- stringstream ss;
- print(ss, t);
- ss.flush();
- s = ss.str();
- }
- void insert(int& t, const string& s) {
- t = merge(t, insert(s.substr(0, s.size() / 2), s.substr(s.size() / 2)));
- }
- int K = 400;
- int vnum = 0;
- vector<string> ans(K);
- vector<vector<vector<int>>> changes(2 * K);
- vector<vector<vector<char>>> changes_i(2 * K);
- vector<vector<vector<int>>> changes_int(2 * K);
- vector<vector<vector<string>>> changes_str(2 * K);
- signed main(int argc, char** argv) {
- int L, Q;
- string S;
- cin >> L >> Q >> S;
- int deco = 0;
- insert(deco, S);
- ans[0] = S;
- int processed = 0;
- int cnt1 = 1;
- int vnum = 1;
- while (Q--) {
- string t;
- cin >> t;
- if (t == "GET") {
- int v, l, r;
- cin >> v >> l >> r;
- --v;
- int p = v / K;
- int off = v % K;
- --off;
- auto& block = changes[p];
- auto& block_str = changes_str[p];
- auto& block_int = changes_int[p];
- auto& block_i = changes_i[p];
- for (int j = l; j <= r; ++j) {
- int cpos = j;
- int curr_off = off;
- while (curr_off > -1) {
- auto& cur_chng = block[curr_off];
- auto& cur_chng_i = block_i[curr_off];
- auto& cur_chng_int = block_int[curr_off];
- auto& cur_chng_str = block_str[curr_off];
- auto x = upper_bound(cur_chng.begin(), cur_chng.end(), cpos);
- --x;
- int idx = x - cur_chng.begin();
- if (cur_chng_i[idx]) {
- cout << cur_chng_str[idx][cpos - cur_chng[idx]];
- break;
- }
- else {
- cpos = cur_chng_int[idx] + cpos - cur_chng[idx];
- --curr_off;
- }
- }
- if (curr_off == -1) {
- cout << ans[p][cpos - 1];
- }
- }
- cout << endl;
- }
- else if (t == "COMMIT") {
- ++processed;
- int c;
- cin >> c;
- int new_treap = 0;
- int copy = deco;
- int removed = 0;
- int curr_idx = 1;
- vector<int> changes_;
- vector<char> changes_i_;
- vector<int> changes_int_;
- vector<string> changes_str_;
- changes_.reserve(c);
- changes_int_.reserve(c);
- changes_i_.reserve(c);
- changes_str_.reserve(c);
- while (c--) {
- string t;
- cin >> t;
- if (t == "add") {
- cin >> t;
- insert(new_treap, t);
- changes_.push_back(curr_idx);
- curr_idx += t.size();
- changes_str_.emplace_back(std::move(t));
- changes_i_.push_back(1);
- changes_int_.push_back(0);
- }
- else {
- int l, r;
- cin >> l >> r;
- auto [a, b] = split(copy, l - 1 - removed);
- auto [c, d] = split(b, r - l + 1);
- new_treap = merge(new_treap, c);
- removed = r;
- copy = d;
- changes_.push_back(curr_idx);
- changes_str_.emplace_back();
- changes_i_.push_back(0);
- changes_int_.push_back(l);
- curr_idx += r - l + 1;
- }
- }
- changes[cnt1 - 1].emplace_back(std::move(changes_));
- changes_str[cnt1 - 1].emplace_back(std::move(changes_str_));
- changes_int[cnt1 - 1].emplace_back(std::move(changes_int_));
- changes_i[cnt1 - 1].emplace_back(std::move(changes_i_));
- deco = new_treap;
- cout << "version " << ++vnum << std::endl;
- if (processed == K - 1) {
- print(ans[cnt1++], deco);
- processed = 0;
- }
- }
- else if (t == "FLUSH") {
- cout << "===" << std::endl;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment