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

时间:2022-04-29 18:35:16

题目大意:给一个字符串,有插入和询问操作,每次往一个位置插入一个字符或者询问第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 second
const int maxq = + ;
const int maxch = + ;
int tree[maxch << ]; inline void pushup(int o){
tree[o] = tree[o << ] + tree[o << | ];
} void buildtree(int o, int l, int r){
if (l == r){
tree[o] = ;
return ;
}
int mid = (l + r) / ;
if (l <= mid) buildtree(o << , l ,mid);
if (r > mid) buildtree(o << | , mid + , 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) / ;
if (pos <= mid) update(o << , l, mid, pos, val);
if (pos > mid) update(o << | , mid + , r, pos, val);
pushup(o);
} int query(int o, int l, int r, int pos){
if (l == r) return l;
int mid = (l + r) / ;
if (tree[o << ] >= pos) return query(o << , l, mid, pos);
if (tree[o << ] < pos) return query(o << | , mid + , r, pos - tree[o << ]);
}
///要知道的东西:询问,初始的ch,线段树节点上的val,线段树该节点下还有多少子节点
struct Query{
int ty, pos, cnt;///表示目前有几个插入的
char val;
Query(int ty = , char val = , int pos = , int cnt = ): 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 = ; i <= Q; i++){
char c[]; scanf("%s", c);
if (c[] == 'I') {
char cc[]; scanf("%s", cc);
int pos; scanf("%d", &pos);
q[i] = Query(c[], cc[], pos, cnt + );///目前该询问下的种类,val和位置,加上已经有了多少个字母了
cnt++;
}
else {
int pos; scanf("%d", &pos);
q[i] = Query(c[], , pos, cnt);
}
}
/*①逆序放入②得到逆序放入以后放入位置的val是多少*/
int n = cnt;
///printf("n = %d\n", n);
buildtree(, , n); for (int i = Q; i >= ; i--){///知道他是在哪个位置的
if (q[i].ty == 'I'){
q[i].pos = min(q[i].pos, q[i].cnt);
int p = query(, , n, q[i].pos); ///线段树里面的位置
tpos[i] = p;
tval[p] = q[i].val;///线段树该位置下的val
update(, , n, p, );
}
}
for (int i = , j = ; i <= n; i++){
if (tval[i] == ){
tval[i] = ch[j]; j++;
}
}
for (int i = ; i <= Q; i++){
if (q[i].ty == 'I'){
update(, , n, tpos[i], );
}
else {
int p = query(, , n, q[i].pos);
printf("%c\n", tval[p]);
}
}
return ;
}