题解 P4008 【[NOI2003] 文本编辑器】

一道简单的数据结构题,直接用splay做即可

对于每一个操作
Move:直接修改光标位置
Insert:将光标所指的位置旋到根,再将它的后继旋到它下面,直接将序列插入为它的左儿子
Dlete:将光标所指的位置旋到根,再将光标加n所指的位置旋到它下面,并将它的左儿子直接赋值为0
Get:将光标所指的位置旋到根,再将光标加n所指的位置旋到它下面,输出它的左儿子
Prev:光标位置减1
Next:光标位置加1

代码

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 2e6 + 50005;

struct tree
{
    int s[2], v, p, siz;
    void init(int _v, int _p)
    {
        s[0] = s[1] = 0;
        v = _v, p = _p, siz = 1;
    }//初始化
} tr[N];
int root, nodes[N], tot, poi;//nodes用来回收删除的节点
char s[N];

void pushup(int p)
{
    tr[p].siz = tr[tr[p].s[0]].siz + tr[tr[p].s[1]].siz + 1;
}

int build(int l, int r, int p)
{
    int u = nodes[tot--], mid = (l + r) >> 1;
    tr[u].init((int)s[mid], p);
    if (l < mid)
        tr[u].s[0] = build(l, mid - 1, u);
    if (r > mid)
        tr[u].s[1] = build(mid + 1, r, u);
    pushup(u);
    return u;
}

void rotate(int x)
{
    int y = tr[x].p, z = tr[y].p;
    int k = tr[y].s[1] == x;
    tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z;
    tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;
    tr[x].s[k ^ 1] = y, tr[y].p = x;
    pushup(y), pushup(x);
}

void splay(int x, int k)
{
    while (tr[x].p != k)
    {
        int y = tr[x].p, z = tr[y].p;
        if (z != k)
        {
            if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y))
                rotate(x);
            else
                rotate(y);
        }
        rotate(x);
    }
    if (!k)
        root = x;
}

int get_k(int k)
{
    int u = root;
    while (u)
    {
        if (tr[tr[u].s[0]].siz >= k)
            u = tr[u].s[0];
        else if (tr[tr[u].s[0]].siz + 1 == k)
            return u;
        else
            k -= tr[tr[u].s[0]].siz + 1, u = tr[u].s[1];
    }
    return -1;
}

void dfs(int u)
{
    if (tr[u].s[0])
        dfs(tr[u].s[0]);
    if (tr[u].s[1])
        dfs(tr[u].s[1]);
    nodes[++tot] = u;
}

void output(int u)
{
    if (tr[u].s[0])
        output(tr[u].s[0]);
    printf("%c", (char)tr[u].v);
    if (tr[u].s[1])
        output(tr[u].s[1]);
}

int main()
{
    for (int i = 1; i < N; i++)
        nodes[++tot] = i;
    int t;
    scanf("%d", &t);
    s[1] = 0, s[2] = 127;
    root = build(1, 2, 0);
    while (t--)
    {
        char op[10];
        int k, n;
        scanf("%s", &op);
        if (op[0] == 'M')
        {
            scanf("%d", &k);
            poi = k;            
        }
        else if (op[0] == 'I')
        {
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
            {
                scanf("%c", &s[i]);
                if ((int)s[i] > 126 || (int)s[i] < 32)
                    i--;
            }
            int l = get_k(poi + 1), r = get_k(poi + 2);
            splay(l, 0), splay(r, l);
            int v = build(1, n, r);
            tr[r].s[0] = v;
            pushup(r), pushup(l);
        }
        else if (op[0] == 'D')
        {
            scanf("%d", &n);
            int l = get_k(poi + 1), r = get_k(poi + n + 2);
            splay(l, 0), splay(r, l);
            dfs(tr[r].s[0]);//回收节点
            tr[r].s[0] = 0;
            pushup(r), pushup(l);
        }
        else if (op[0] == 'G')
        {
            scanf("%d", &n);
            int l = get_k(poi + 1), r = get_k(poi + n + 2);
            splay(l, 0), splay(r, l);
            output(tr[r].s[0]);
            printf("\n");
        }
        else if (op[0] == 'P')
            poi--;
        else
            poi++;
    }
    return 0;
}
posted @ 2021-02-02 15:34  DSHUAIB  阅读(59)  评论(0编辑  收藏  举报