poj 2887 塊狀數組/線段樹

Big String
Time Limit: 1000MS   Memory Limit: 131072K
Total Submissions: 5952   Accepted: 1405

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:

  1. 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.
  2. 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

ab
7
Q 1
I c 2
I d 4
I e 2
Q 5
I f 1
Q 3

Sample Output

a
d
e

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 1001

char 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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章