Big String 块状数组(或者说平方分割)

                              Big String 

给一个字符串,长度不超过 106,有两种操作:

  1. 在第 i 个字符的前面添加一个字符 ch

  2. 查询第 k 个位置是什么字符

操作的总数不超过 2000

如果直接模拟的话,移动到后面的数据量太大。我们分块的话,就可以优化,减少移动的量。  很典型的块状数组。块状数组的next指向的是一块,而不是一个。这里用整数代替了指针。

每一个块就是一个对象。这题用面向对象编程。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <string>
  7 #include <vector>
  8 #include <set>
  9 #include <map>
 10 #include <stack>
 11 #include <queue>
 12 #include <sstream>
 13 #include <iomanip>
 14 using namespace std;
 15 typedef long long LL;
 16 const int INF=0x4fffffff;
 17 const int EXP=1e-5;
 18 const int MS=2100;
 19
 20 struct node
 21 {
 22     int size,next;
 23     char str[MS];
 24     void push(char ch)
 25     {
 26         str[size++]=ch;
 27     }
 28     void insert(int pos,char ch)
 29     {
 30         for(int i=size++;i>pos;i--)
 31             str[i]=str[i-1];
 32         str[pos]=ch;
 33     }
 34
 35 }nodes[MS];
 36
 37 char S[500*MS];
 38 int SIZE,cnt,Q;
 39
 40 void input()
 41 {
 42     scanf("%s",S);
 43     scanf("%d",&Q);
 44     int len=strlen(S);
 45     SIZE=(int)sqrt(0.1+len+Q);
 46     cnt=0;
 47     nodes[cnt].size=0;
 48     for(int i=0;i<len;i++)
 49     {
 50         if(nodes[cnt].size>=SIZE)
 51         {
 52             nodes[cnt].next=cnt+1;
 53             nodes[++cnt].size=0;
 54         }
 55         nodes[cnt].push(S[i]);
 56     }
 57     nodes[cnt].next=-1;
 58 }
 59
 60 //设一个块的最大容量为2*SIZE,当满了就要从后面使用一块来补充
 61 void updata(int id)
 62 {
 63     if(nodes[id].size<2*SIZE)    // 我们是在区间插入一个字符后在更新,所以要留一个位置
 64         return ;
 65     ++cnt;
 66     int i,j,k=nodes[id].size;
 67     for(i=SIZE,j=0;i<k;i++,j++)
 68         nodes[cnt].str[j]=nodes[id].str[i];
 69     nodes[cnt].size=j;
 70     nodes[id].size=SIZE;
 71     nodes[cnt].next=nodes[id].next;
 72     nodes[id].next=cnt;
 73 }
 74
 75 void solve()
 76 {
 77     int i,j,pos;
 78     char cmd[MS];
 79     for(i=0;i<Q;i++)
 80     {
 81         scanf("%s",cmd);
 82         if(cmd[0]==‘Q‘)
 83         {
 84             scanf("%d",&pos);
 85             for(j=0;pos>nodes[j].size;j=nodes[j].next)
 86                 pos-=nodes[j].size;
 87             printf("%c\n",nodes[j].str[pos-1]);
 88         }
 89         else
 90         {
 91             scanf("%s%d",cmd,&pos);
 92             for(j=0;pos>nodes[j].size&&nodes[j].next!=-1;j=nodes[j].next)
 93                 pos-=nodes[j].size;
 94             nodes[j].insert(min(pos-1,nodes[j].size),cmd[0]);
 95             updata(j);
 96         }
 97     }
 98 }
 99
100 int main()
101 {
102     input();
103     solve();
104     return 0;
105 }

   

时间: 2025-01-02 03:39:59

Big String 块状数组(或者说平方分割)的相关文章

POJ 2887 Big String (块状数组)

题意:给一个字符串(<=1000000)和n个操作(<2000),每个操作可以在某个位置插入一个字符,或者查询该位置的字符.问查询结果. 思路:块状数组. 如果将原来的字符串都存在一起,每次插入肯定会超时. 而操作数比较少,考虑使用分块法.假设原字符串长度为L,则取每块长度l=sqrt(L).这样每次插入,我们需要用sqrt(L)的时间找到对应的块,再用sqrt(L)在该块进行插入.查询同样需要sqrt(L)找到该块,如果用数组实现可以O(1)找到目标元素.(我尝试用stl链表来做,结果超时了

POJ2887 Big String(块状数组)

参考:http://blog.csdn.net/htt_h/article/details/44862813 题意: 给你一个不超过1e6的字符串,和不超过2000次的操作 操作分为两种: 1.将一个字符插入到某个位置的前面 2.询问当前位置的字符 思路: 学了一发块状数组,就是把1e6的原串分为1e3份,每份长度相同, 由于操作不超过两千次,那每一份的长度不会超过3e3, 可以开一个1e3*3e3的字符数组来存储串,开一个1e3的长度数组记录每部分的长度 这样就可以在较短的时间内完成插入和查找

hdu 5030 Rabbit&#39;s String(后缀数组&amp;二分)

Rabbit's String Time Limit: 40000/20000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 288    Accepted Submission(s): 108 Problem Description Long long ago, there lived a lot of rabbits in the forest. One day, the

hdu 5030 Rabbit&#39;s String(后缀数组)

题目链接:hdu 5030 Rabbit's String 题目大意:给定k和一个字符串,要求将字符串拆分成k个子串.然后将每个子串中字典序最大的子串选出来,组成一个包含k个字符串的集合,要求这个集合中字典序最大的字符串字典序最小. 解题思路:网赛的时候试图搞了一下这道题,不过水平还是有限啊,后缀数组也是初学,只会切一些水题.赛后看了一下别人的题解,把这题补上了. 首先对整个字符串做后缀数组,除了处理出sa,rank,height数组,还要处理处f数组,f[i]表示说以0~sa[i]开头共有多少

POJ 2104 K-th Number(区间第k大数)(平方分割,归并树,划分树)

题目链接: http://poj.org/problem?id=2104 解题思路: 因为查询的个数m很大,朴素的求法无法在规定时间内求解.因此应该选用合理的方式维护数据来做到高效地查询. 如果x是第k个数,那么一定有 (1)在区间中不超过x的数不少于k个 (2)在区间中小于x的数有不到k个 因此,如果可以快速求出区间里不超过x的数的个数,就可以通过对x进行二分搜索来求出第k个数是多少. 接下来,我们来看一下如何计算在某个区间里不超过x个数的个数.如果不进行预处理,那么就只能遍历一遍所有元素.

POJ2104 K-th Number 静态区间第k最值 平方分割

干掉这道题的那一刻,我只想说:我终于**的AC了!!! 最终内存1344K,耗时10282ms,比起归并树.划分树以及其他各种黑科技,这个成绩并不算光彩⊙﹏⊙ 但至少,从最初的无数次TLE到最终的AC,这过程见证了一个二分算法的艰辛优化 先贴代码: 1 const int bktSize=1024; 2 const int bktMaxIdx=bktSize-1; 3 const int bktCount=128; 4 const int bktDigit=10; 5 const int max

Javascript的String和数组

本章讨论Javascript的String和数组. 所有语言中对String和数组的操作是很普遍的,掌握好它们的操作,会让我们在lu代码的时候事半功倍. 一.String String顾名思义,就是字符串的意思 var  string="Iamhandsome"; 就创建了一个名为string的字符串,它的值为Iamhandsome. String是Javascript基本数据类型之一.String也可以看作是Javascript的一个对象.对象有很多方法的 下面来看看它的方法,由于方

有序数组每个数平方后,不同数字的个数?O(n)

此乃一道笔试题,当时的确也出来啦.(但是在细节上还是出错啦,对多次重复出现的数字可能会重复计数,没有记录上次删除的元素) 如题,有序数组,可以知道平方之后在两边的数据较大,中间的数据较小. 因此可以使用两个下标,从两边向中间扫描.将绝对值大的数字删掉,计数即可,并记录刚才删除的数值的绝对值,以免出现多次相同的数据,重复计数的问题. 具体看完整代码: 1 #include <iostream> 2 #include <vector> 3 #include <algorithm&

块状数组

定义: 块状数组是基于分块思想的数据结构,较基于分治思想的数据结构如线段树.平衡树等效率较低,但通用性更强.在块状数组的基础上加以扩展,就可以得到块状链表. 原理: 普通数组在处理一些区间问题时,复杂度通常会退化至O(n).一个朴素的想法就是将这个数组分为若干个子区间,同时维护这些子区间的统计值,如区间和.区间最值等.对于某个子区间,如果操作区间覆盖子区间,则在整体上进行修改并打标记.如果操作区间部分覆盖子区间,则将该块标记下放,对区间中被覆盖部分的元素进行暴力操作. 设数组长度为n,将其分为s