思路
大傻逼题,用脚写都能过
一道小模拟,只需要记录一下指针的位置,然后正常的FHQ分裂-操作-合并即可。甚至不需要区间和并。
可能读入是本题的唯一难度?
Code
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 3e6 + 10;
namespace FHQ {
char val[N];
int lc[N], rc[N], key[N], siz[N];
bool lazy[N];
int tot, root;
std::mt19937 Rand(114514);
struct stk {
int st[N], cur = 0;
stk() { cur = 0; }
inline void pop() { --cur; }
inline int top() { return st[cur]; }
inline void push(int x) { st[++cur] = x; }
inline bool empty() { return cur == 0; }
} stk;
inline void make_node(int &rt, char x) {
if(!stk.empty()) rt = stk.top(), stk.pop();
else rt = ++tot;
val[rt] = x, key[rt] = Rand(), siz[rt] = 1, lc[rt] = rc[rt] = 0;
// cout << "New node was made, serial = " << rt << endl;
}
inline void push_up(int rt) {
siz[rt] = siz[lc[rt]] + 1 + siz[rc[rt]];
}
void split(int rt, int x, int &u, int &v) {
if(!rt) return u = v = 0, void();
if(x > siz[lc[rt]]) split(rc[rt], x - siz[lc[rt]] - 1, rc[u = rt], v);
else split(lc[rt], x, u, lc[v = rt]);
push_up(rt);
}
int merge(int u, int v) {
if(!u || !v) return u + v;
if(key[u] > key[v]) {
rc[u] = merge(rc[u], v);
return push_up(u), u;
} else {
lc[v] = merge(u, lc[v]);
return push_up(v), v;
}
}
void clc(int x) { val[x] = lc[x] = rc[x] = siz[x] = key[x] = 0; stk.push(x); }
void del(int rt) {
if(!rt) return;
del(lc[rt]), del(rc[rt]), clc(rt);
}
void insert(char x) {
int new_node; make_node(new_node, x);
root = merge(root, new_node);
}
string ans;
void cout_mid(int rt) {
if(!rt) return;
cout_mid(lc[rt]);
cout << val[rt];
cout_mid(rc[rt]);
}
void get_mid(int rt) {
if(!rt) return;
get_mid(lc[rt]);
ans.push_back(val[rt]);
get_mid(rc[rt]);
}
string get(int rt) { ans = "", get_mid(rt); return ans; }
}
inline int get_opid(string op) {
if(op[0] == 'I') return 1;
else if(op[0] == 'M') return 2;
else if(op[0] == 'D') return 3;
else if(op[0] == 'G') return 4;
else if(op[0] == 'P') return 5;
else if(op[0] == 'N') return 6;
return 0;
}
using FHQ::root;
using FHQ::val;
inline void solve() {
int q = 0; cin >> q;
int tot = 0, cur = 0;
vector<string> ans;
for(int c = 1; c <= q; c++) {
string op; cin >> op;
int opid = get_opid(op);
if(opid == 1) { // Insert operation
// cout << "!!! NOW LEN = " << tot << endl;
int n = 0; cin >> n, tot += n;
string s = "";
int le = 0;
while(le < n) {
char nw = getchar();
if(nw >= 32 && nw <= 126) {
s.push_back(nw);
le++;
}
}
int spl, spr, now = 0;
for(auto chr : s) {
int new_node; FHQ::make_node(new_node, chr);
now = FHQ::merge(now, new_node);
}
// cout << "Now cur.pos = " << cur << ", insert a string: " << s << endl;
// cout << "_>> @Debug: root = " << root << ", new root = " << now << endl;
if(cur == 0) {
root = FHQ::merge(now, root);
} else {
FHQ::split(root, cur, spl, spr);
root = FHQ::merge(FHQ::merge(spl, now), spr);
}
} else if (opid == 2) { // Cur move to k
int k = 0; cin >> k, cur = k;
} else if (opid == 3) { // Delete n char
int n = 0; cin >> n, tot -= n;
int spl, spm, spr;
FHQ::split(root, cur + n, spl, spr);
FHQ::split(spl, cur, spl, spm);
FHQ::del(spm);
root = FHQ::merge(spl, spr);
} else if (opid == 4) { // Output n char
int n = 0; cin >> n;
int spl, spm, spr;
FHQ::split(root, cur + n, spl, spr);
FHQ::split(spl, cur, spl, spm);
ans.emplace_back(FHQ::get(spm));
root = FHQ::merge(FHQ::merge(spl, spm), spr);
} else if (opid == 5) { // Move cur to front
cur--;
} else if (opid == 6) { // Move cur to back
cur++;
}
// cout << endl << "OP Round = " << c << ", state = ";
// FHQ::cout_mid(root); cout << endl << endl;
}
for(auto s : ans) cout << s << endl;
}
signed main() {
// ios_base::sync_with_stdio(false), cin.tie(0);
int t = 1; // cin >> t;
while(t--) solve();
return 0;
}
169

被折叠的 条评论
为什么被折叠?



