[NOI2003]Editor(块状链表)

传送门

看了看块状链表,就是数组和链表的合体。

看上去好高大尚,思想也很简单。

但是发现代码量也不是很小,而且代码理解起来也是费尽得很,倒不如splay用起来顺手。

在加上适用范围貌似不是特别广,所以只把模板贴在这,只当了解思想,暂时先不使用。(也不会用啊)

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<queue>
  5 using namespace std;
  6
  7 const int N=1<<25;
  8 const int blocksize=20000;
  9 const int blocknum=N/blocksize*3;
 10
 11 int T,_;
 12 int cur;
 13 char str[5000005],opt[100];
 14 queue <int> q;
 15 struct node
 16 {
 17     char data[blocksize+111];
 18     int len,nxt;
 19 }a[blocknum+1000];
 20
 21 void init()
 22 {
 23     for (int i=1;i<=blocknum;++i) q.push(i);
 24     a[0].len=0; a[0].nxt=-1;
 25 }
 26 void read(int len)
 27 {
 28     int i=-1;
 29     while (i<len-1)
 30     {
 31         i++;
 32         char c=getchar();
 33         str[i]=c;
 34         if (c<32||c>126) i--;
 35     }
 36 }
 37 //新开一个块的节点
 38 int newnode()
 39 {
 40     int temp=q.front(); q.pop();
 41     return temp;
 42 }
 43 //回收块的节点
 44 void delnode(int t)
 45 {
 46     q.push(t);
 47 }
 48 //找到pos所在的块,并使pos表示在当前块中的位置
 49 void find(int &pos,int &now)
 50 {
 51     for (now=0;a[now].nxt!=-1&&pos>a[now].len;now=a[now].nxt)
 52         pos-=a[now].len;
 53 }
 54 //将新快赋值
 55 void fillnode(int pos,int n,char data[],int nxt)
 56 {
 57     a[pos].nxt=nxt; a[pos].len=n;
 58     memcpy(a[pos].data,data,n);
 59 }
 60 //将块pos在p位置前后分开,变成两个块
 61 void split(int pos,int p)
 62 {
 63     if (a[pos].len==p) return;
 64     int t=newnode();
 65     fillnode(t,a[pos].len-p,a[pos].data+p,a[pos].nxt);
 66     a[pos].nxt=t; a[pos].len=p;
 67 }
 68 //把碎块合并
 69 void maintain(int pos)
 70 {
 71     int t;
 72     for (;pos!=-1;pos=a[pos].nxt)
 73         for (t=a[pos].nxt;t!=-1&&a[pos].len+a[t].len<blocksize;t=a[t].nxt)
 74         {
 75             memcpy(a[pos].data+a[pos].len,a[t].data,a[t].len);
 76             a[pos].len+=a[t].len; a[pos].nxt=a[t].nxt; delnode(t);
 77         }
 78 }
 79 //在光标pos处插入长度为n的str
 80 void insert(int pos,int n)
 81 {
 82     int now,i,t;
 83     //now表示光标所在的块,pos表示光标在这个块中的位置
 84     find(pos,now);
 85     split(now,pos);
 86     for (i=0;i+blocksize<=n;i+=blocksize)
 87     {
 88         t=newnode();
 89         fillnode(t,blocksize,str+i,a[now].nxt);
 90         a[now].nxt=t;
 91         now=t;
 92     }
 93     if (i<n)
 94     {
 95         t=newnode();
 96         fillnode(t,n-i,str+i,a[now].nxt);
 97         a[now].nxt=t;
 98     }
 99     maintain(now);
100 }
101 //从光标pos开始删除长度为n的字符串
102 void del(int pos,int n)
103 {
104     int i,now,t;
105     //now表示光标所在的块,pos表示光标在这个块中的位置
106     find(pos,now);
107     split(now,pos);
108     //找到删除的末尾的点所处的块
109     for (i=a[now].nxt;i!=-1&&n>a[i].len;i=a[i].nxt)
110         n-=a[i].len;
111     split(i,n); i=a[i].nxt;
112     for (t=a[now].nxt;t!=i;t=a[now].nxt)
113         a[now].nxt=a[t].nxt,delnode(t);
114     maintain(now);
115 }
116 //从pos这个位置开始输出长度为n的字符串
117 void get(int pos,int n)
118 {
119     int i,now,t;
120     find(pos,now);
121     i=min(n,a[now].len-pos);
122     memcpy(str,a[now].data+pos,i);
123     for (t=a[now].nxt;t!=-1&&i+a[t].len<=n;t=a[t].nxt)
124     {
125         memcpy(str+i,a[t].data,a[t].len);
126         i+=a[t].len;
127     }
128     if (i<n&&t!=-1) memcpy(str+i,a[t].data,n-i);
129     str[n]=0;
130 }
131 int main()
132 {
133     init();
134     scanf("%d",&T);
135     while (T--)
136     {
137         scanf("%s",opt);
138         if (opt[0]==‘M‘) scanf("%d",&cur);//改变光标的位置
139         if (opt[0]==‘I‘)//插入一段区间
140         {
141             scanf("%d",&_);
142             read(_);
143             insert(cur,_);
144         }
145         if (opt[0]==‘P‘) cur--;//光标左移
146         if (opt[0]==‘N‘) cur++;//光标右移
147         if (opt[0]==‘D‘)//删除一段区间
148         {
149             scanf("%d",&_);
150             del(cur,_);
151         }
152         if (opt[0]==‘G‘)//输出一段区间
153         {
154             scanf("%d",&_);
155             get(cur,_);
156             puts(str);
157         }
158     }
159 }

时间: 2024-10-11 09:17:43

[NOI2003]Editor(块状链表)的相关文章

1507: [NOI2003]Editor(块状链表)

1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4157  Solved: 1677[Submit][Status][Discuss] Description Input 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例). 除了回车符之外,输入文件的所有字

【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L

Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r. 为了体现在线操作,对于一个询问(x,y): l = min ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).r = max ( ((x+lastans) mod N)+1 , ((y+last

【POJ2887】【块状链表】Big String

Description You are given a string and supposed to do some string manipulations. Input The first line of the input contains the initial string. You can assume that it is non-empty and its length does not exceed 1,000,000. The second line contains the

c++之路进阶——块状链表(弹飞绵羊)

2333 弹飞绵羊 2010年省队选拔赛湖南 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description Lostmonkey发明了一种超级反弹装置.为了在绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿一条直线摆放 n个反弹装置,并按从前往后的方式将反弹装置依次编号为 0 到 n-1,对 0≤i≤n-1,为第 i 个反弹装置设定了初始弹力系数 ki,当绵羊落到第 i 个反弹装置上时,它将被往后

c++之路——块状链表(教主的魔法)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  gryz2016 Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 711  Solved: 309[Submit][Stat

hdu 1754 块状链表 单点修改+单点查询

经典的线段树题目,也可以用块状链表做. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namespace std; 6 7 const int N = 200000; 8 const int M = 800; 9 int n, m, tot; 10 11 int max( int a, int b ) 12 { 13 retu

poj 2887 块状链表

块状链表第一题,懒得写成链表形式的,所以写成了静态链表. 思想还是很简单的,就是进行分块查找和插入,和建立索引有点像,复杂度是根号的,实现起来比较容易,由于这个题插入操作不多,所以没有写split函数, 因为没有删除操作,所以也没有写union函数,随后有空再补上吧. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namesp

【BZOJ1500】【块状链表】SuperMemo

Description Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格. Output 对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行. Sample Input 9 8 2 -6 3 5 1 -5 -3 6 3 GET-SUM 5 4 MAX-SUM INSERT 8 3 -5 7 2 DELETE 12

【块状链表】AutSky_JadeK的块状链表模板+总结(STL版)

Part 1.块状链表.   定位 插入 删除 数组 O(1) O(n) O(n) 链表 O(n) O(1) O(1) 对于线性表的以上常见操作来说,数组和链表都无法有效地解决.但是,若我们将链表的每个节点存成一个数组,使得链表里每个节点的数据拼接起来就是原先的线性表中的内容(即块状链表),并且数组的大小合适的话,以上的操作都能比较好地解决了.根据均值不等式,若每个块的大小定为sqrt(n)左右最优,此时块数也是sqrt(n)左右,易证.以下是块状链表的基础操作的思想.复杂度和代码. 一.声明.