【YBTOJ】【Luogu P2596】[ZJOI2006]书架
链接:
题目大意:
维护一个序列,支持移动元素,查询某元素位置,查询某位置元素。
正文:
考虑用 fhq-Treap。
主要解决 fhq-Treap 不能通过编号找节点的问题。假设我们要求下图红点的位置:
可以每次往父亲节点跳,如果它右孩子则编号就要加上左孩子大小加一,这个一实际上是父亲的零头。也就是说,只要维护了父亲节点就能求出位置。
这样下来,就是 fhq-Treap 基本操作了。
代码:
int read()
{
int f = 1, x = 0;
char c = getchar();
while (c < '0' || c > '9') {if(c == '-')f = -f;c = getchar();}
while (c >= '0' && c <= '9')x = x * 10 + c - '0', c= getchar();
return f * x;
}
const int N = 1e5 + 10;
int n, m;
string s;
struct FHQ_Treap
{
struct BST
{
int ch[2], fa, siz, dat, val;
}t[N];
FHQ_Treap() {srand(1919810);}
int tot, root, id[N];
int New(int val)
{
t[++tot].siz = 1,
t[tot].val = val,
t[tot].dat = rand();
return tot;
}
void Update(int x)
{
t[x].siz = 1;
if (t[x].ch[0]) t[x].siz += t[t[x].ch[0]].siz, t[t[x].ch[0]].fa = x;
if (t[x].ch[1]) t[x].siz += t[t[x].ch[1]].siz, t[t[x].ch[1]].fa = x;
}
int Merge(int x, int y)
{
if (!x || !y) return x + y;
if (t[x].dat < t[y].dat)
{
t[x].ch[1] = Merge(t[x].ch[1], y);
Update(x);
return x;
}else
{
t[y].ch[0] = Merge(x, t[y].ch[0]);
Update(y);
return y;
}
}
void Split(int x, int kth, int &l, int &r)
{
if (!x) { l = r = 0;return;}
if (t[t[x].ch[0]].siz < kth)
l = x, Split(t[x].ch[1], kth - t[t[x].ch[0]].siz - 1, t[x].ch[1], r);
else
r = x, Split(t[x].ch[0], kth, l, t[x].ch[0]);
Update(x);
}
int Pos(int x)
{
int ans = 1 + t[t[x].ch[0]].siz;
for (; t[x].fa; x = t[x].fa)
if (x == t[t[x].fa].ch[1])
ans += t[t[t[x].fa].ch[0]].siz + 1;
return ans;
}
}t;
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
scanf ("%d%d", &n, &m);
for (int i = 1, x; i <= n; i++)
scanf ("%d", &x), t.id[x] = i, t.root = t.Merge(t.root, t.New(x));
for (int i = 1; i <= m; i++)
{
cin >> s;
int x = read();
int y = t.Pos(t.id[x]);
if (s[0] == 'T')
{
int a, b, c;
t.Split(t.root, y - 1, a, b);
t.Split(b, 1, b, c);
t.root = t.Merge(b, t.Merge(a, c));
continue;
}
if (s[0] == 'B')
{
int a, b, c;
t.Split(t.root, y - 1, a, b);
t.Split(b, 1, b, c);
t.root = t.Merge(a, t.Merge(c, b));
continue;
}
if (s[0] == 'I')
{
int G = read();
if (!G) continue;
int a, b, c, d;
t.Split(t.root, y - 1 - (G == -1), a, b);
t.Split(b, 1, b, c);
t.Split(c, 1, c, d);
t.root = t.Merge(a, t.Merge(t.Merge(c, b), d));
continue;
}
if (s[0] == 'A')
{
printf ("%d\n", y - 1);
continue;
}
int a, b, c;
t.Split(t.root, x - 1, a, b);
t.Split(b, 1, b, c);
printf ("%d\n", t.t[b].val);
t.root = t.Merge(t.Merge(a, b), c);
}
return 0;
}