[FHQ模板] P4008 [NOI2003] 文本编辑器

思路

大傻逼题,用脚写都能过

一道小模拟,只需要记录一下指针的位置,然后正常的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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HeartFireY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值