POJ 2887:Big String(分块)

时间:2023-01-17 18:36:13

http://poj.org/problem?id=2887

题意:给出一个字符串,还有n个询问,第一种询问是给出一个位置p和字符c,要在位置p的前面插入c(如果p超过字符串长度,自动插在最后),第二种询问是给出一个位置p,查找第p个位置的字符(p保证合法)。

思路:暴力分块。一开始建成块之后,每次插入就在每个块的字符串插入字符,因为询问最多只有2000个,所以就算极端情况也不会超时。

注意:sz和cnt其中一个要向上取整。用string类会超时。

 #include <cstring>
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
using namespace std;
char s[][];
char str[];
int n, block[], sz, cnt; void Build() {
sz = sqrt(n);
cnt = (n + sz - ) / sz; // 记得向上取整, 因为这WA了一次
for(int i = ; i < n; i++) s[i / sz + ][block[i / sz + ]++] = str[i];
} void Insert(char c, int p) {
int i;
for(i = ; i <= cnt; i++) {
if(p - block[i] <= ) break;
p -= block[i];
}
if(i == cnt + ) { s[cnt][block[cnt]++] = c; return ; }
block[i]++;
int len = strlen(s[i]);
for(int j = len - ; j >= p - ; j--) s[i][j+] = s[i][j];
s[i][p-] = c;
} void Query(int p) {
int i;
for(i = ; i <= cnt; i++) {
if(p - block[i] <= ) break;
p -= block[i];
}
printf("%c\n", s[i][p-]);
} int main() {
scanf("%s", str); n = strlen(str);
int q; scanf("%d", &q);
Build();
while(q--) {
char op[], c[]; int num;
scanf("%s", op);
if(op[] == 'I') {
scanf("%s%d", c, &num);
Insert(c[], num);
} else {
scanf("%d", &num);
Query(num);
}
}
return ;
}