标签:style blog http color 使用 os io for
题意:给一个字符串(<=1000000)和n个操作(<2000),每个操作可以在某个位置插入一个字符,或者查询该位置的字符。问查询结果。
思路:块状数组。
如果将原来的字符串都存在一起,每次插入肯定会超时。
而操作数比较少,考虑使用分块法。假设原字符串长度为L,则取每块长度l=sqrt(L)。这样每次插入,我们需要用sqrt(L)的时间找到对应的块,再用sqrt(L)在该块进行插入。查询同样需要sqrt(L)找到该块,如果用数组实现可以O(1)找到目标元素。(我尝试用stl链表来做,结果超时了)
这样最坏的情况下,一个块最多有2000个字符,当然操作不会超时,但是数组要开得足够大。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <list> #define ll long long using namespace std; int Maxn, N ; int sum[1005]; struct BlockList { int size; char dat[2005]; int at(int pos) { return dat[pos]; } void insert(int pos,char c) { for(int i=++size; i>pos; --i) dat[i]=dat[i-1]; dat[pos]=c; } void push_back(char c) { dat[++size]=c; } }; BlockList block[1005]; char query(int s,int p) { return block[s].at(p); } void insert(int s,int p,char c) { p=min(p,block[s].size+1); block[s].insert(p,c); } void maintain() { for(int i=1; i<=Maxn; ++i) sum[i]=sum[i-1]+block[i].size; } void MyInsert(int pos,char c) { int p=lower_bound(sum+1,sum+1+Maxn,pos)-(sum); insert(p,pos-sum[p-1],c); maintain(); } int MyQuery(int pos) { int p=lower_bound(sum+1,sum+1+Maxn,pos)-(sum); return query(p,pos-sum[p-1]); } char str[1000005]; void init() { int len=strlen(str)+N; Maxn=sqrt(len*1.0)+1; for(int i=0; str[i]; ++i) block[i/Maxn+1].push_back(str[i]); maintain(); } int main() { gets(str); int pos; char p[3],s[3]; scanf("%d",&N); init(); while(N--) { scanf("%s",p); if(p[0]==‘I‘) { scanf("%s%d",s,&pos); MyInsert(pos,s[0]); } else { scanf("%d",&pos); printf("%c\n",MyQuery(pos)); } } return 0; }
POJ 2887 Big String (块状数组),布布扣,bubuko.com
标签:style blog http color 使用 os io for
原文地址:http://www.cnblogs.com/kkkwjx/p/3870059.html