poj 2887 块状数组/线段树
来源:互联网 发布:电话轰炸机原理知乎 编辑:程序博客网 时间:2024/05/18 22:50
Description
You are given a string and supposed to do some string manipulations.
Input
The first line of the input contains the initial string. You can assume that it is non-empty and its length does not exceed 1,000,000.
The second line contains the number of manipulation commands N (0 < N ≤ 2,000). The following N lines describe a command each. The commands are in one of the two formats below:
- I ch p: Insert a character ch before the p-th character of the current string. If p is larger than the length of the string, the character is appended to the end of the string.
- Q p: Query the p-th character of the current string. The input ensures that the p-th character exists.
All characters in the input are digits or lowercase letters of the English alphabet.
Output
For each Q command output one line containing only the single character queried.
Sample Input
ab7Q 1I c 2I d 4I e 2Q 5I f 1Q 3
Sample Output
ade
Source
字符串总长度不超过10^6,插入操作不超过2000次。可以用块状数组存储字符串,比如10^6分成1000行存,每行1000个,并用len[]数组记录每行的字符串长度。插入第k个就找到第k个字符应该属于哪一行,直接插入,操作次数也不超过改行字符串长度也就是几千。
块状数组思想是平方分割法,将长度为n的数组分sqrt(n)块,每个长度为n/sqrt(n)=sqrt(n),对每个区间进行操作只需要O(sqrt(n))的复杂度。
这题是插入和查询第k个点,一般还可以用线段树离线输出结果。先把所有的查询和插入都进来,倒叙模拟插入,用线段树更新和统计区间和。
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;#define maxn 1001char s[maxn*maxn];char a[maxn][maxn*3]; //插入最多2000次,每行最多3000个int len[maxn]; //记录每一行字符个数const int b = 1000; //默认分成最多1000行int row; //共几行char query(int k) //查询第k个{ int cnt = 0; for(int i = 0; i < row; i++){ if(cnt+len[i]>= k){ return a[i][k-cnt-1]; } cnt+=len[i]; }}void add(char ch, int k) //插入到第k个{ int cnt = 0; int r; for(int i = 0; i < row; i++){ if(cnt+len[i] >= k){ r = i; break; } if(i == row-1) {r = row-1; break;} cnt+=len[i]; } int pos = k-cnt-1; if(pos >= len[r]) pos = len[r]; for(int i = len[r]; i >= pos+1; i--) a[r][i] = a[r][i-1]; a[r][pos] = ch; len[r]++;}int main(){ while(scanf("%s", s)==1){ memset(len, 0, sizeof(len)); int slen = strlen(s); int perl = (slen+b-1)/b; //每行保存的字符个数 row = (slen-1)/perl+1; //共多少行 for(int i = 0; i < row; i++) len[i] = perl; for(int i = 0; i < slen; i++) a[i/perl][i%perl] = s[i]; len[row-1] = (slen-1)%perl+1; int n; scanf("%d", &n); while(n--){ char op[3]; int k; scanf("%s", op); if(op[0] == 'Q'){ scanf("%d", &k); printf("%c\n", query(k)); } else{ scanf("%s %d", op, &k); add(op[0], k); } } } return 0;}
- poj 2887 块状数组/线段树
- poj 2887 块状数组
- 【POJ 2887】Big String(块状数组)
- Poj 2887 Big String(块状数组)
- CodeVS 1080 线段树练习 分块 块状数组
- 块状数组
- [POJ 2887] Big String [块状链表]
- POJ-2887(块状链表)
- 【POJ 2887】Big String 块状链表
- POJ 2887Big String(块状链表)
- poj 2887 Big String 块状链表
- POJ 2887 Big String 块状链表
- [POJ 2104] K-th Number (块状数组)
- 块状数组+归并树学习 poj2104+hdu2665
- poj 2481 Cows(树状数组 | 线段树)
- poj 3067 Japan(线段树 | 树状数组)
- POJ 3067 树状数组 线段树
- poj 2155 二维线段树/树状数组
- 5
- DTO的应用
- ubuntu14.04 apache修改网站根目录以及默认网页
- javascript中的平稳退化
- T001_UT001_0007
- poj 2887 块状数组/线段树
- 【线段树专题】poj2104
- Ubuntu常见命令记录
- mdk工具关键字的定义。
- GitHub傻瓜式教程(一、创建仓库)
- T001_UT001_0008
- 程序员解决问题的60个策略
- 3
- Java包命名规则引发的思考