题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1507

题意:一个文本编辑器,模拟以下操作:

思路:块状链表的主要操作:

(1)find(p,b):找到位置p在链表的位置b;

(2)split(b,p):将第b块分裂成两块,前一块大小为p;

(3)maintain(b):将b块之后的碎片合并;

利用以上三种操作可以完成插入串、删除一段串、得到一段串三种操作。另外三种操作比较简单。

(1)insert(p,n,str):在位置p之后插入长度为n的串str。find(p,b),split(b,p),之后将str插入b之后,最后maintain(b)一下;

(2)erase(p,n):在位置p之后删除长度为n的一段。find(p,b),split(b,p),之后从b之后删除若干块。这里可能最后一块也是需要split的。

(3)get(p,n):得到p之后长度为n的一段。find(p,b),split(b,p),之后从b之后取出长度为n的串,这里可能最后一个串也是需要split的。

const int N=1<<25;
const int BLOCKSIZE=20000;
const int BLOCKNUM=N/BLOCKSIZE*3;

queue<int> Q;

int newNode()
{
    int temp=Q.front();
    Q.pop();
    return temp;
}

void delNode(int t)
{
    Q.push(t);
}

struct node
{
    char data[BLOCKSIZE];
    int len,next;
};

node a[BLOCKNUM];

void find(int &p,int &b)
{
    for(b=0;a[b].next!=-1&&p>a[b].len;b=a[b].next)
    {
        p-=a[b].len;
    }
}

void fillNode(int b,int n,char data[],int nextB)
{
    a[b].next=nextB;
    a[b].len=n;
    memcpy(a[b].data,data,n);
}

void split(int b,int p)
{
    if(a[b].len==p) return;
    int t=newNode();
    fillNode(t,a[b].len-p,a[b].data+p,a[b].next);
    a[b].next=t;
    a[b].len=p;
}

void maintain(int b)
{
    int t;
    for(;b!=-1;b=a[b].next)
    {
        for(t=a[b].next;t!=-1&&a[b].len+a[t].len<=BLOCKSIZE;t=a[b].next)
        {
            memcpy(a[b].data+a[b].len,a[t].data,a[t].len);
            a[b].len+=a[t].len;
            a[b].next=a[t].next;
            delNode(t);
        }
    }
}

void insert(int p,int n,char str[])
{
    int i,b,t;
    find(p,b); split(b,p);
    for(i=0;i+BLOCKSIZE<=n;i+=BLOCKSIZE)
    {
        t=newNode();
        fillNode(t,BLOCKSIZE,str+i,a[b].next);
        a[b].next=t;
        b=t;
    }
    if(i<n)
    {
        t=newNode();
        fillNode(t,n-i,str+i,a[b].next);
        a[b].next=t;
    }
    maintain(b);
}

void erase(int p,int n)
{
    int i,b,t;
    find(p,b); split(b,p);
    for(i=a[b].next;i!=-1&&n>a[i].len;i=a[i].next)
    {
        n-=a[i].len;
    }
    split(i,n); i=a[i].next;
    for(t=a[b].next;t!=i;t=a[b].next)
    {
        a[b].next=a[t].next;
        delNode(t);
    }
    maintain(b);
}

void get(int p,int n,char str[])
{
    int i,b,t;
    find(p,b);i=min(n,a[b].len-p);
    memcpy(str,a[b].data+p,i);
    for(t=a[b].next;t!=-1&&i+a[t].len<=n;t=a[t].next)
    {
        memcpy(str+i,a[t].data,a[t].len);
        i+=a[t].len;
    }
    if(i<n&&t!=-1) memcpy(str+i,a[t].data,n-i);
    str[n]=0;
}

void init()
{
    int i;
    FOR1(i,BLOCKNUM-1) Q.push(i);
    a[0].next=-1;
    a[0].len=0;
}

char str[N];

void read(int n)
{
    int i;
    char c;
    FOR0(i,n)
    {
        c=getchar();
        str[i]=c;
        if(c<32||c>126) i--;
    }
}

int main()
{
    init();
    int cur=0;
    char op[10];
    int n;
    rush()
    {
        RD(op);
        if(op[0]=='M') RD(cur);
        else if(op[0]=='I')
        {
            RD(n);
            read(n);
            insert(cur,n,str);
        }
        else if(op[0]=='D')
        {
            RD(n);
            erase(cur,n);
        }
        else if(op[0]=='G')
        {
            RD(n);
            get(cur,n,str);
            puts(str);
        }
        else if(op[0]=='P') cur--;
        else if(op[0]=='N') cur++;
    }
}

BZOJ 1507 Editor(块状链表)的更多相关文章

  1. 【BZOJ 1507】【NOI 2003】&【Tyvj P2388】Editor 块状链表模板题

    2016-06-18 当时关于块状链表的想法是错误的,之前维护的是一个动态的$\sqrt{n}$,所以常数巨大,今天才知道原因TwT,请不要参照这个程序为模板!!! 模板题水啊水~~~ 第一次写块状链 ...

  2. 【BZOJ-1507】Editor 块状链表

    1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 3397  Solved: 1360[Submit][Stat ...

  3. BZOJ 3217: ALOEXT (块状链表套trie)

    第一次写块状链表,发现还挺好写的,但是一点地方写错加上强制在线就会各种姿势WA/TLE/RE爆- 想法就是分块后,在每一个块上维护最大值和次大值,还在每一个块上维护一棵trie树来求异或最大值.散块直 ...

  4. BZOJ 1507 Editor

    Description Input 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它 ...

  5. BZOJ 4864: [BeiJing 2017 Wc]神秘物质 (块状链表/平衡树 )

    这就是一道数据结构裸题啊,最大极差就是区间最大值减最小值,最小极差就是相邻两个数差的最小值.然后平衡树splay/treap或者块状链表维护就行了. 第一次自己写块状链表,蛮好写,就是长..然后就BZ ...

  6. bzoj 3809 Gty的二逼妹子序列(莫队算法,块状链表)

    [题意] 回答若干个询问,(l,r,a,b):区间[l,r]内权值在[a,b]的数有多少[种]. [思路] 考虑使用块状链表实现莫队算法中的插入与删除. 因为权值处于1..n之间,所以我们可以建一个基 ...

  7. 洛谷.4008.[NOI2003]editor文本编辑器(块状链表)

    题目链接 st(n)表示sqrt(n) 为使块状链表不会退化,通常将每块的大小S维持在[st(n)/2,2st(n)]中,这样块数C也一定[st(n)/2,2st(n)]中 在此使用另一种方法(方便) ...

  8. [NOI2003]Editor(块状链表)

    传送门 看了看块状链表,就是数组和链表的合体. 看上去好高大尚,思想也很简单. 但是发现代码量也不是很小,而且代码理解起来也是费尽得很,倒不如splay用起来顺手. 在加上适用范围貌似不是特别广,所以 ...

  9. 块状链表 bzoj 3343教主的魔法

    //块状链表//分块排序,然后每次查找时在暴力查找头和尾两个块.//中间那些块,因为有序所以只需2分查找即可.我用的是lower_pound();//插入是,也是头和尾暴力插入,中间那些加到一个累计里 ...

随机推荐

  1. SPOJ - DQUERY 主席树

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32356 Given a sequence of n numbers ...

  2. 项目前端技术-learn

    赶鸭子上架 之 前端学习 目前项目中的前端用到的技术主要是:1. bootstrap框架; 2. 基于javscript的jQuery, jQuery ui; 3. dust前端模板引型.

  3. NYOJ-73 比大小 AC 分类: NYOJ 2014-01-17 21:29 195人阅读 评论(0) 收藏

    典型的大数题目,这只是大数的比较,到时还有大数加减乘除,更加还有乘方,对于大数,一般用数组或者字符串,因为其他的结构类型一般都没有那么大 的范围!! 这道题目需要你仔细回想怎么比较俩个数字的大小,考虑 ...

  4. 引擎设计跟踪(九.14.2g) 将GNUMake集成到Visual Studio

    最近在做纹理压缩工具, 以及数据包的生成. shader编译已经在vs工程里面了, 使用custom build tool, build命令是调用BladeShaderComplier, 并且每个文件 ...

  5. [翻译]Kafka Streams简介: 让流处理变得更简单

    Introducing Kafka Streams: Stream Processing Made Simple 这是Jay Kreps在三月写的一篇文章,用来介绍Kafka Streams.当时Ka ...

  6. HDOJ 3177 Crixalis&#39;s Equipment

    Crixalis's Equipment Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  7. org.eclipse.wst.common.project.facet.core.xml文件模板,解决eclipse编译报错。

    <?xml version="1.0" encoding="UTF-8"?> <faceted-project> <fixed f ...

  8. CentOS7.0重置Root的密码

    CentOS7.0重置Root的密码 首先进入开启菜单,按下e键进入编辑现有的内核,如下图所示 然后滚动列表,找到ro,将它替换成rw,并加上init=/sysroot/bin/sh,最终变为如下图 ...

  9. [Qt] 界面美化 [2013-06-17更新](转载)

    - 经验总结 1. 可用对话框(QDialog)模拟类似Android中toast的效果.     - 设置程序界面风格 在main函数中QApplication::setStyle("wi ...

  10. jdom处理的XML Document 和String 之间的相互转化

    package util; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileWriter; ...