poj 2887 Big String

题目连接

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

Big String

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

abcdf
7
Q 1
I g 2
I h 10
I k 1
Q 1
Q 3
Q 8

Sample Output

a
k
g
f

伸展树的插入,单点查询。。

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<set>
using std::set;
using std::sort;
using std::pair;
using std::swap;
using std::vector;
using std::multiset;
#define pb(e) push_back(e)
#define sz(c) (int)(c).size()
#define mp(a, b) make_pair(a, b)
#define all(c) (c).begin(), (c).end()
#define iter(c) __typeof((c).begin())
#define cls(arr, val) memset(arr, val, sizeof(arr))
#define cpresent(c, e) (find(all(c), (e)) != (c).end())
#define rep(i, n) for(int i = 0; i < (int)n; i++)
#define tr(c, i) for(iter(c) i = (c).begin(); i != (c).end(); ++i)
const int N = 1 << 20;
char buf[N];
struct Node {
    int s;
    char dat;
    Node *fa, *ch[2];
    inline void set(int i, char j, Node *p) {
        s = i, dat = j;
        fa = ch[0] = ch[1] = p;
    }
    inline void push_up() {
        s = ch[0]->s + ch[1]->s + 1;
    }
    inline bool dir() const {
        return fa->ch[0] == this;
    }
    inline void link(Node *x, bool d) {
        ch[d] = x;
        x->fa = this;
    }
};
struct SplayTree {
    Node *root, *tail, *null, stack[N];
    inline void init(int n) {
        tail = &stack[0];
        null = tail++;
        null->set(0, ‘.‘, NULL);
        root = newNode(‘.‘);
        root->link(newNode(‘.‘), 1);
        Node *x = built(1, n);
        root->ch[1]->link(x, 0);
        root->ch[1]->push_up();
        root->push_up();
        splay(x, null);
    }
    inline Node *built(int l, int r) {
        if(l > r) return null;
        int mid = (l + r) >> 1;
        Node *p = newNode(buf[mid - 1]);
        p->ch[0] = built(l, mid -1);
        if(p->ch[0] != null) p->ch[0]->fa = p;
        p->ch[1] = built(mid + 1, r);
        if(p->ch[1] != null) p->ch[1]->fa = p;
        p->push_up();
        return p;
    }
    inline Node *newNode(char dat) {
        Node *p = tail++;
        p->set(1, dat, null);
        return p;
    }
    inline void rotate(Node *&x, bool d) {
        Node *y = x->fa;
        y->ch[!d] = x->ch[d];
        x->fa = y->fa;
        if(x->ch[d]->s) x->ch[d]->fa = y;
        if(y->fa->s) y->fa->ch[!y->dir()] = x;
        x->ch[d] = y;
        y->fa = x, y->push_up();
        if (y == root) root = x;
    }
    inline void splay(Node *x, Node *f) {
        if(x == root) return;
        while(x->fa != f) {
            if(x->fa->fa == f) {
                rotate(x, x->dir());
            } else {
                bool d = x->fa->dir();
                if(d == x->dir()) rotate(x->fa, d), rotate(x, d);
                else rotate(x, !d), rotate(x, d);
            }
        }
        x->push_up();
    }
    inline Node *select(Node *x, int k) {
        for(int t = 0; x->s; ) {
            t = x->ch[0]->s;
            if(t == k) break;
            else if(k < t) x = x->ch[0];
            else k -= t + 1, x = x->ch[1];
        }
        return x;
    }
    inline void insert(char dat, int k) {
        if(k > root->s) k = root->s - 2;
        k--;
        splay(select(root, k), null);
        splay(select(root, k + 1), root);
        Node *x = newNode(dat);
        root->ch[1]->link(x, 0);
        root->ch[1]->push_up();
        root->push_up();
        splay(x, null);
    }
    inline char operator[](int k) {
        splay(select(root, k), null);
        return root->dat;
    }
}spt;
int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w+", stdout);
#endif
    int q, k;
    char op, dat;
    while(~scanf("%s", buf)) {
        scanf("%d", &q);
        spt.init(strlen(buf));
        while(q--) {
            getchar();
            scanf("%c", &op);
            if(op == ‘Q‘) {
                scanf(" %d", &k);
                printf("%c\n", spt[k]);
            } else {
                scanf(" %c %d", &dat, &k);
                spt.insert(dat, k);
            }
        }
    }
    return 0;
}
时间: 2024-10-12 20:32:52

poj 2887 Big String的相关文章

POJ 2887 Big String (块状数组)

题意:给一个字符串(<=1000000)和n个操作(<2000),每个操作可以在某个位置插入一个字符,或者查询该位置的字符.问查询结果. 思路:块状数组. 如果将原来的字符串都存在一起,每次插入肯定会超时. 而操作数比较少,考虑使用分块法.假设原字符串长度为L,则取每块长度l=sqrt(L).这样每次插入,我们需要用sqrt(L)的时间找到对应的块,再用sqrt(L)在该块进行插入.查询同样需要sqrt(L)找到该块,如果用数组实现可以O(1)找到目标元素.(我尝试用stl链表来做,结果超时了

POJ 2887 Big String 线段树 离线处理

一开始看的时候没什么思路,后来一看卧槽不是简单的离线处理么.反着插入一遍然后直接查询就好了. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r const int maxq = 2e3 + 10; const

POJ 2406 Power String 后缀数组

这题曾经用KMP做过,用KMP 做非常的简单,h函数自带的找循环节功能. 用后缀数组的话,首先枚举循环节长度k,然后比较LCP(suffix(k + 1), suffix(0)) 是否等于len - k, 如果相等显然k就是一个循环节. 得到LCP的话可以通过预处理出所有点和0的lcp就好了.另外倍增法构造后缀数组还有用RMQ来搞lcp nlogn是不行的,会超时,所以可以dc3走起了.. #include <cstdio> #include <cstring> #include

(块状链表) poj 2887

Big String Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 5936   Accepted: 1397 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 ass

POJ 2887

#include <iostream> #include <string> #define MAXN 2000 using namespace std; struct node { char c; int place; }; node _node[MAXN]; int index; void fun_q(int place); int len; string s; int main() { //freopen("acm.acm","r",st

POJ 2406 Power String(KMP)

解题思路: 依旧是利用next数组的性质,m % (m - next[m]) == 0; #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> #include <queue> #include <

poj 2887 块状链表

块状链表第一题,懒得写成链表形式的,所以写成了静态链表. 思想还是很简单的,就是进行分块查找和插入,和建立索引有点像,复杂度是根号的,实现起来比较容易,由于这个题插入操作不多,所以没有写split函数, 因为没有删除操作,所以也没有写union函数,随后有空再补上吧. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cmath> 5 using namesp

好题 线段树对数据的保存+离线的逆向插入 POJ 2887

题目大意:给一个字符串,有插入和询问操作,每次往一个位置插入一个字符或者询问第p个位置的字符是什么. 思路:我们离线询问,逆向把所有的字符都插入给线段树,然后再查询就好了,每次都要记得插入线段树的最后的位置,然后要把这个位置给保存下来在O(1)查询即可. //看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <cstdio> #include<cstring> #include<algorithm> #include<

POJ 2406 Power String

算出next数组. 对于任何一个循环字串,len-next[len]必为最小循环节长度 若len%(len-next[len])==0 即为循环字串,n=len/(len-next[len]) 否则输出1 代码: #include<cstdio> #include<cstring> using namespace std; const int N=1e6+10; char str[N]; int next[N],ans,len; void make() { int i=0,j=-1