POJ 2887 Big String 块状链表

题目:

http://poj.org/problem?id=2887

题意:

初始给定一个字符串,然后有两种操作: I ch p 在第 p 个字符前插入字符ch Q p 查询第 p 个位置上的字符。下标均是从1开始

思路:

用的块状链表。块状链表的基本操作有定位、插入、分裂、合并和删除,各个操作均为 O(n) 。这个题算是裸题了,留个模板

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 1000000 + 10, M = 2000 + 10;

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

struct block
{
    int sz, next;
    char s[M];
    void init()
    {
        sz = 0, next = -1;
    }
}g[M];
int new_block() //分配新块
{
    int t = que.front(); que.pop();
    g[t].init();
    return t;
}
void del_block(int t) //删除块
{
    que.push(t);
}
void block_split(int idx, int k) //块分裂
{
    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_init(char *str) //初始化
{
    while(! que.empty()) que.pop();
    for(int i = 0; i < M; i++) que.push(i);
    head = new_block();
    int idx = head;
    int len = strlen(str), i = 0;
    while(i < len)
    {
        int sz = min(M, len - i);
        memcpy(g[idx].s, str + i, sizeof(char) * sz);
        g[idx].sz = sz;
        i += sz;
        if(i < len)
        {
            int tot = new_block();
            g[idx].next = tot;
            idx = g[idx].next;
        }
    }
    for(int i = head; i != -1; i = g[i].next)
        if(g[i].sz == M) block_split(i, M>>1); //块满,及时进行分裂
}
void block_locate(int &idx, int &k) //块定位
{
    while(idx != -1 && k > g[idx].sz)
        k -= g[idx].sz, idx = g[idx].next;
}
char block_query(int k)
{
    int idx = head;
    block_locate(idx, k);
    return g[idx].s[k-1];
}
void block_insert(int k, char ch) //插入
{
    int idx = head;
    block_locate(idx, k);
    if(k >= g[idx].sz) g[idx].s[g[idx].sz] = ch;
    else
    {
        for(int i = g[idx].sz-1; i >= k; i--)
            g[idx].s[i+1] = g[idx].s[i];
        g[idx].s[k] = ch;
    }
    g[idx].sz++;
    if(g[idx].sz == M) block_split(idx, M>>1);
}
int main()
{
    char op, ch;
    int n, p;
    while(~ scanf("%s", str))
    {
        block_init(str);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
        {
            scanf(" %c", &op);
            if(op == 'Q')
            {
                scanf("%d", &p);
                printf("%c\n", block_query(p));
            }
            else
            {
                scanf(" %c%d", &ch, &p);
                block_insert(p-1, ch);
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值