线段树
这种每次在第几个位置插入元素的题,都可以用线段树,从最后一次插入开始来查找每次插入的元素的最终位置。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
#define maxl 2000005
#define maxn 2005
struct Elem
{
bool cmd;
int p;
char ch;
int pos;
} elem[maxn];
struct Node
{
Node *pl;
Node *pr;
int lnum, rnum, l, r;
} tree[maxl * 3];
char st1[maxl], st[maxl];
int n, len, ncount;
void input()
{
scanf("%s%d", st1, &n);
len = strlen(st1);
for (int i = 0; i < n; i++)
{
char st[5];
scanf("%s", st);
if (st[0] == 'I')
{
elem[i].cmd = true;
scanf("%s%d", st, &elem[i].p);
len++;
if (elem[i].p > len)
elem[i].p = len;
elem[i].ch = st[0];
}
else
{
elem[i].cmd = false;
scanf("%d", &elem[i].p);
}
}
}
void build_tree(Node *proot, int l, int r)
{
int mid = (l + r) / 2;
proot->lnum = mid - l + 1;
proot->rnum = r - mid;
proot->l = l;
proot->r = r;
if (l == r)
return;
ncount++;
proot->pl = tree + ncount;
ncount++;
proot->pr = tree + ncount;
build_tree(proot->pl, l, mid);
build_tree(proot->pr, mid + 1, r);
}
int query(Node *proot, int a)
{
if (proot->l == proot->r)
return proot->l;
if (a > proot->lnum)
return query(proot->pr, a - proot->lnum);
return query(proot->pl, a);
}
void update(Node *proot, int pos, int a)
{
if (proot->l == proot->r)
return;
int mid = (proot->l + proot->r) / 2;
if (pos > mid)
{
proot->rnum += a;
update(proot->pr, pos, a);
}
else
{
proot->lnum += a;
update(proot->pl, pos, a);
}
}
void work()
{
memset(st, 0, sizeof(st));
for (int i = n - 1; i >= 0; i--)
if (elem[i].cmd)
{
elem[i].pos = query(tree, elem[i].p);
st[elem[i].pos] = elem[i].ch;
update(tree, elem[i].pos, -1);
}
int j = 0;
for (int i = 1; i <= len; i++)
if (!st[i])
st[i] = st1[j++];
for (int i = 0; i < n; i++)
if (elem[i].cmd)
update(tree, elem[i].pos, 1);
else
printf("%c\n",st[query(tree, elem[i].p)]);
}
int main()
{
//freopen("t.txt", "r", stdin);
input();
ncount = 0;
build_tree(tree, 1, len);
work();
return 0;
}