初识 块状数组
2018-01-04 20:47
309 查看
问题
给出一个长串,然后给出n个操作,操作有两种,在某个位置插入一个字符,或者查询第x个位置上的字符是什么
对于这个问题,我们有两种解决方案。
1:数组
查询 O(1) 但是插入最坏可以达到 O(len)
2:链表
插入 O(1) 但是查询最坏也可以达到O(len)
所以如何优化这个问题。
这里介绍一种数据结构——块状数组
何为块状数组?
普通的数组,每个节点都是连续的。
而块状数组是把一个大块分为若干个小块,然后连接起来,因此得名块状数组。
数组块数*每个块的最大长度>=总的元素+操作个数,即分块以后,每个块都有个增大的空间(让其大于操作个数即可)
分块,就是优美的暴力~
如何查询与插入?
sum[i]为第一块到第i块字符的总个数。
再插入时我们可以利用二分快速寻找位置所对应的块号。
而在查询时,也是利用二分来查询块号输出。
在最坏情况下=sqrt(str)+n;
在平均情况下=sqrt(str+n);
block_num,块数:
准确讲,=(str+n)/block_len
结合平均情况来讲,block_num=block_len=sqrt(str+n)、
代码没用结构体封装,因为我不喜欢。
初级块状数组,代码较短,仅支持插入与查询操作。
题目链接
给出一个长串,然后给出n个操作,操作有两种,在某个位置插入一个字符,或者查询第x个位置上的字符是什么
对于这个问题,我们有两种解决方案。
1:数组
查询 O(1) 但是插入最坏可以达到 O(len)
2:链表
插入 O(1) 但是查询最坏也可以达到O(len)
所以如何优化这个问题。
这里介绍一种数据结构——块状数组
何为块状数组?
普通的数组,每个节点都是连续的。
而块状数组是把一个大块分为若干个小块,然后连接起来,因此得名块状数组。
数组块数*每个块的最大长度>=总的元素+操作个数,即分块以后,每个块都有个增大的空间(让其大于操作个数即可)
分块,就是优美的暴力~
如何查询与插入?
sum[i]为第一块到第i块字符的总个数。
再插入时我们可以利用二分快速寻找位置所对应的块号。
而在查询时,也是利用二分来查询块号输出。
在最坏情况下=sqrt(str)+n;
在平均情况下=sqrt(str+n);
block_num,块数:
准确讲,=(str+n)/block_len
结合平均情况来讲,block_num=block_len=sqrt(str+n)、
代码没用结构体封装,因为我不喜欢。
初级块状数组,代码较短,仅支持插入与查询操作。
题目链接
#include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> #define il inline using namespace std; const int maxm=2100; int block_len,block_num,n;//块长以及块数 int sum[maxm];//从1块到当前块的总字符个数 char str[1100000]; struct node{ int size; char date[maxm<<1]; }block[maxm]; il void get_sum()//统计 { sum[1]=block[1].size; for(int i=2;i<=block_num;i++) sum[i]=sum[i-1]+block[i].size; } il void push_in(int id,char s){block[id].date[++block[id].size]=s;}//初始插入 il void init() { int str_len=strlen(str); block_len=block_num=sqrt((double)str_len+(double)n); for(int i=1;i<=block_num;i++) block[i].size=0,sum[i]=0; for(int i=0;i<str_len;i++) push_in(i/block_len+1,str[i]); get_sum(); } il void insert(int id,int pos,char s) { if(pos>block[id].size) push_in(id,s); else { for(int i=++block[id].size;i>pos;i--) block[id].date[i]=block[id].date[i-1];//移动插入 block[id].date[pos]=s; } get_sum(); } il char ask(int id,int pos){return block[id].date[pos];} int main() { scanf("%s",str); scanf("%d",&n); init(); char qus[3],ss[3]; for(int i=1,pos;i<=n;i++) { scanf("%s",qus); if(qus[0]=='Q') { scanf("%d",&pos); int block_id=lower_bound(sum+1,sum+block_num+1,pos)-sum; int block_pos=pos-sum[block_id-1];//不要忘记-1 printf("%c\n",ask(block_id,block_pos)); } else { scanf("%s%d",ss,&pos); int block_id=lower_bound(sum+1,sum+block_num+1,pos)-sum; int block_pos=pos-sum[block_id-1]; insert(block_id,block_pos,ss[0]); } } return 0; }
相关文章推荐
- codefroce D. Powerful array[初识块状数组]
- codefroce D. Powerful array[初识块状数组]
- 初识块状数组/块状链表(讲解+ 例题)
- 初识go语言之 数组与切片(创建,遍历,删除,插入,复制)
- 块状数组(hdu3207 Highway)
- 初识数组
- Java基础学习——数组初识(1)
- CodeVS 1080 线段树练习 分块 块状数组
- C++学习笔记(第六章 初识指针 及 指针与数组 之一)
- Big String-POJ2887块状数组
- 初识JavaScript 变量, 操作符, 数组
- C语言从零开始——day3(数组初识)
- 我的Ruby学习历程之初识数组
- Big String-POJ2887块状数组
- 【POJ 2887】Big String(块状数组)
- HDU 5193 Go to movies Ⅱ(块状数组套树状数组)
- 数组初识
- 指针初识5(指针与数组)
- hdu 5193 Go to movies Ⅱ 块状链表 + 树状数组
- java初识之多维数组