块状链表

2024-08-15

通过块状链表的结构,实现大量数据的快速插入和删除

#include <bits/stdc++.h>
#define io cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define LL long long
#define ULL unsigned long long
#define EPS 1e-8
#define INF 0x7fffffff
#define SUB -INF - 1
using namespace std;
int block = 2500;
list<vector<char>> List;
typedef list<vector<char>>::iterator it;
it Find(int &pos)
{
    for (it i = List.begin();; i++)
    {
        if (i == List.end() || pos <= i->size())
            return i;
        pos -= i->size();
    }
}
void Output(int L, int R)
{
    it L_block = Find(L), R_block = Find(R);
    for (it it1 = L_block;; it1++)
    {
        int a;
        it1 == L_block ? a = L : a = 0;
        int b;
        it1 == R_block ? b = R : b = it1->size();
        for (int i = a; i < b; i++)
            putchar(it1->at(i));
        if (it1 == R_block)
            break;
    }
    putchar('\n');
}
it Next(it x) { return ++x; }
void Merge(it x)
{
    x->insert(x->end(), Next(x)->begin(), Next(x)->end());
    List.erase(Next(x));
}
void Split(it x, int pos)
{
    if (pos == x->size())
        return;
    List.insert(Next(x), vector<char>(x->begin() + pos, x->end()));
    x->erase(x->begin() + pos, x->end());
}
void Update()
{
    for (it i = List.begin(); i != List.end(); i++)
    {
        while (i->size() >= (block << 1))
            Split(i, i->size() - block);
        while (Next(i) != List.end() && i->size() + Next(i)->size() <= block)
            Merge(i);
        while (Next(i) != List.end() && Next(i)->empty())
            List.erase(Next(i));
    }
}
void Insert(int pos, const vector<char> &ch)
{
    it curr = Find(pos);
    if (!List.empty())
        Split(curr, pos);
    List.insert(Next(curr), ch);
    Update();
}
void Delete(int L, int R)
{
    it L_block, R_block;
    L_block = Find(L);
    Split(L_block, L);
    R_block = Find(R);
    Split(R_block, R);
    R_block++;
    while (Next(L_block) != R_block)
        List.erase(Next(L_block));
    Update();
}
int main()
{
    vector<char> ch;
    int len, pos, n;
    cin >> n;
    while (n--)
    {
        char opt[7];
        cin >> opt;
        if (opt[0] == 'M')
            cin >> pos;
        if (opt[0] == 'I')
        {
            ch.clear();
            cin >> len;
            ch.resize(len);
            for (int i = 0; i < len; i++)
            {
                ch[i] = getchar();
                while (ch[i] < 32 || ch[i] > 126)
                    ch[i] = getchar();
            }
            Insert(pos, ch);
        }
        if (opt[0] == 'D')
        {
            cin >> len;
            Delete(pos, pos + len);
        }
        if (opt[0] == 'G')
        {
            cin >> len;
            Output(pos, pos + len);
        }
        if (opt[0] == 'P')
            pos--;
        if (opt[0] == 'N')
            pos++;
    }
    return 0;
}