POJ 2887 Big String (块状数组)

时间:2022-11-30 18:35:44

题意:给一个字符串(<=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 ;
];
struct BlockList
{
    int size;
    ];
    int at(int pos)
    {
        return dat[pos];
    }
    void insert(int pos,char c)
    {
        ];
        dat[pos]=c;
    }
    void push_back(char c)
    {
        dat[++size]=c;
    }
};
BlockList block[];
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+);
    block[s].insert(p,c);
}
void maintain()
{
    ; i<=Maxn; ++i)
        sum[i]=sum[i-]+block[i].size;
}
void MyInsert(int pos,char c)
{
    ,sum++Maxn,pos)-(sum);
    insert(p,pos-sum[p-],c);
    maintain();
}
int MyQuery(int pos)
{
    ,sum++Maxn,pos)-(sum);
    ]);
}
];
void init()
{
    int len=strlen(str)+N;
    Maxn=sqrt(len*;
    ; str[i]; ++i)
        block[i/Maxn+].push_back(str[i]);
    maintain();
}
int main()
{
    gets(str);
    int pos;
    ],s[];
    scanf("%d",&N);
    init();
    while(N--)
    {
        scanf("%s",p);
        ]=='I')
        {
            scanf("%s%d",s,&pos);
            MyInsert(pos,s[]);
        }
        else
        {
            scanf("%d",&pos);
            printf("%c\n",MyQuery(pos));
        }
    }
    ;
}