bzoj 1507 Editor 块状链表

题目:

http://www.lydsy.com/JudgeOnline/problem.php?id=1507

题意:

这里写图片描述

思路:

用块状链表写的,操作还是挺繁琐的。。。

#include <bits/stdc++.h>

using namespace std;

const int N = 4000000 + 10, M = 3000+10;
const int block_num = 3000 + 100;

queue<int> que;
int head;
char str[N];

struct block
{
    int sz, next;
    char s[M];
    void init()
    {
        sz = 0, next = -1;
    }
}g[block_num];
int new_block()
{
    int t = que.front(); que.pop();
    g[t].init();
    return t;
}
void del_block(int t)
{
    que.push(t);
}
void block_init()
{
    while(! que.empty()) que.pop();
    for(int i = 0; i < block_num; i++) que.push(i);
    head = new_block();
}
void block_split(int idx, int k) //把块分裂
{
    if(g[idx].sz == k) return;
    int tot = new_block();
    memcpy(g[tot].s, g[idx].s + k, sizeof(char) * (g[idx].sz - k));
    g[tot].sz = g[idx].sz - k, g[idx].sz = k;
    g[tot].next = g[idx].next, g[idx].next = tot;
}
void block_locate(int &idx, int &k)
{
    while(idx != -1 && k > g[idx].sz)
        k -= g[idx].sz, idx = g[idx].next;
}
void block_merge(int idx) //合并零碎的块
{
    for(int i = idx; i != -1; i = g[i].next)
    {
        for(int j = g[i].next; j != -1; j = g[j].next)
        {
            if(g[i].sz + g[j].sz <= M)
            {
                memcpy(g[i].s + g[i].sz, g[j].s, sizeof(char) * g[j].sz);
                g[i].sz += g[j].sz, g[i].next = g[j].next;
                del_block(j);
            }
            else break;
        }
    }
}
void block_insert(int k, int n, char *str) 
{
    int idx = head;
    block_locate(idx, k);
    block_split(idx, k);
    int i = 0;
    while(i < n)
    {
        int sz = min(M, n - i);
        int tot = new_block();
        memcpy(g[tot].s, str + i, sizeof(char) * sz);
        g[tot].sz = sz;
        g[tot].next = g[idx].next, g[idx].next = tot;
        idx = g[idx].next;
        i += sz;
    }
    block_merge(head);
}
void block_delete_str(int k, int n)
{
    int idx = head, tk = k;
    block_locate(idx, tk);
    block_split(idx, tk);
    int st = idx, st_next = g[idx].next;

    idx = head, tk = k + n;
    block_locate(idx, tk);
    block_split(idx, tk);
    int en = idx, en_next = g[idx].next;

    for(int i = st_next; i != en_next; i = g[i].next) del_block(i);
    g[st].next = en_next;
    block_merge(head);
}
void block_print(int k, int n, char *str)
{
    int idx = head;
    block_locate(idx, k);
    int len = 0;
    for(int i = idx; i != -1 && n > 0; i = g[i].next)
    {
        int sz = min(n, g[i].sz - k);
        memcpy(str + len, g[i].s + k, sizeof(char) * sz);
        len += sz, n -= sz;
        k = 0;
    }
    str[len] = '\0';
    puts(str);
}
int main()
{
    int t, cur = 0;
    char op[20];
    block_init();
    scanf("%d", &t);
    for(int i = 1; i <= t; i++)
    {
        scanf("%s", op);
        if(op[0] == 'M')
        {
            int k;
            scanf("%d", &k);
            cur = k;
        }
        else if(op[0] == 'I')
        {
            int n;
            scanf("%d", &n);
            int j = 0;
            while(j < n)
            {
                char ch = getchar();
                if(ch >= 32 && ch <= 126) str[j++] = ch;
            }
            block_insert(cur, n, str);
        }
        else if(op[0] == 'D')
        {
            int n;
            scanf("%d", &n);
            block_delete_str(cur, n);
        }
        else if(op[0] == 'G')
        {
            int n;
            scanf("%d", &n);
            block_print(cur, n, str);
        }
        else if(op[0] == 'P') cur--;
        else if(op[0] == 'N') cur++;
    }
    return 0;
}

另:rope大法好

#include <bits/stdc++.h>
#include <ext/rope>

using namespace std;
using namespace __gnu_cxx;

const int N = 2000000 + 10;
rope<char> rs;
char str[N];

int main()
{
    int n, m, cur = 0;
    char op[20];
    scanf("%d", &n);
    while(n--)
    {
        scanf("%s", op);
        if(op[0] == 'M') scanf("%d", &cur);
        else if(op[0] == 'I')
        {
            scanf("%d", &m);
            int i = 0;
            while(i < m)
            {
                char ch = getchar();
                if(ch >= 32 && ch <= 126) str[i++] = ch;
            }
            str[i] = '\0';
            int len = rs.size();
            rs.insert(cur, str);
        }
        else if(op[0] == 'D')
        {
            scanf("%d", &m);
            rs.erase(cur, m);
        }
        else if(op[0] == 'G')
        {
            scanf("%d", &m);
            printf("%s\n", rs.substr(cur, m).c_str());
        }
        else if(op[0] == 'P') cur--;
        else if(op[0] == 'N') cur++;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值