首页 > 代码库 > 好题 线段树对数据的保存+离线的逆向插入 POJ 2887
好题 线段树对数据的保存+离线的逆向插入 POJ 2887
题目大意:给一个字符串,有插入和询问操作,每次往一个位置插入一个字符或者询问第p个位置的字符是什么。
思路:我们离线询问,逆向把所有的字符都插入给线段树,然后再查询就好了,每次都要记得插入线段树的最后的位置,然后要把这个位置给保存下来在O(1)查询即可。
//看看会不会爆int!数组会不会少了一维!//取物问题一定要小心先手胜利的条件#include <cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define LL long long#define ALL(a) a.begin(), a.end()#define pb push_back#define mk make_pair#define fi first#define se secondconst int maxq = 2000 + 5;const int maxch = 1002000 + 5;int tree[maxch << 2];inline void pushup(int o){ tree[o] = tree[o << 1] + tree[o << 1 | 1];}void buildtree(int o, int l, int r){ if (l == r){ tree[o] = 1; return ; } int mid = (l + r) / 2; if (l <= mid) buildtree(o << 1, l ,mid); if (r > mid) buildtree(o << 1 | 1, mid + 1, r); pushup(o);}void update(int o, int l, int r, int pos, int val){ if (l == r && l == pos){ tree[o] = val; return ; } int mid = (l + r) / 2; if (pos <= mid) update(o << 1, l, mid, pos, val); if (pos > mid) update(o << 1 | 1, mid + 1, r, pos, val); pushup(o);}int query(int o, int l, int r, int pos){ if (l == r) return l; int mid = (l + r) / 2; if (tree[o << 1] >= pos) return query(o << 1, l, mid, pos); if (tree[o << 1] < pos) return query(o << 1 | 1, mid + 1, r, pos - tree[o << 1]);}///要知道的东西:询问,初始的ch,线段树节点上的val,线段树该节点下还有多少子节点struct Query{ int ty, pos, cnt;///表示目前有几个插入的 char val; Query(int ty = 0, char val = 0, int pos = 0, int cnt = 0): ty(ty), val(val), pos(pos), cnt(cnt){}}q[maxch];int tpos[maxch], Q;char tval[maxch], ch[maxch];int main(){ scanf("%s", ch); int len = strlen(ch); scanf("%d", &Q); int cnt = len; for (int i = 1; i <= Q; i++){ char c[2]; scanf("%s", c); if (c[0] == ‘I‘) { char cc[2]; scanf("%s", cc); int pos; scanf("%d", &pos); q[i] = Query(c[0], cc[0], pos, cnt + 1);///目前该询问下的种类,val和位置,加上已经有了多少个字母了 cnt++; } else { int pos; scanf("%d", &pos); q[i] = Query(c[0], 0, pos, cnt); } } /*①逆序放入②得到逆序放入以后放入位置的val是多少*/ int n = cnt; ///printf("n = %d\n", n); buildtree(1, 1, n); for (int i = Q; i >= 1; i--){///知道他是在哪个位置的 if (q[i].ty == ‘I‘){ q[i].pos = min(q[i].pos, q[i].cnt); int p = query(1, 1, n, q[i].pos); ///线段树里面的位置 tpos[i] = p; tval[p] = q[i].val;///线段树该位置下的val update(1, 1, n, p, 0); } } for (int i = 1, j = 0; i <= n; i++){ if (tval[i] == 0){ tval[i] = ch[j]; j++; } } for (int i = 1; i <= Q; i++){ if (q[i].ty == ‘I‘){ update(1, 1, n, tpos[i], 1); } else { int p = query(1, 1, n, q[i].pos); printf("%c\n", tval[p]); } } return 0;}
好题 线段树对数据的保存+离线的逆向插入 POJ 2887
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。