文艺平衡树

【模板】文艺平衡树

题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列。 其中需要提供以下操作:翻转一个区间,例如原有序序列是 $5\ 4\ 3\ 2\ 1$,翻转区间是 $[2,4]$ 的话,结果是 $5\ 2\ 3\ 4\ 1$。

输入输出格式

输入格式

 

第一行两个正整数 $n,m$,表示序列长度与操作个数。序列中第 $i$ 项初始为 $i$。 接下来 $m$ 行,每行两个正整数 $l,r$,表示翻转的区间。

输出格式

 

输出一行 $n$ 个正整数,表示原始序列经过 $m$ 次变换后的结果。

输入输出样例

输入样例 #1

5 3
1 3
1 3
1 4

输出样例 #1

4 3 2 1 5

说明

【数据范围】 对于 $100\%$ 的数据,$1 \le n, m \leq 100000 $,$1 \le l \le r \le n$。
 
 

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

#define getsize(p) (p ? p->size : 0)

struct Node
{

    int size;
    int rank, val;
    int rev;
    Node *ls, *rs;

    void push_up()
    {
        size = getsize(ls) + getsize(rs) + 1;
    }

    void pushD()
    {
        if (!rev)
            return;
        if (ls)
            ls->rev ^= 1;
        if (rs)
            rs->rev ^= 1;
        rev = 0;
        swap(ls, rs);
    }

} pool[N * 2], *root;

void split(Node *p, Node *&p_l, Node *&p_r, int x)
{
    if (!p)
    {
        p_l = p_r = NULL;
        return;
    }

    p->pushD();

    if (getsize(p->ls) + 1 <= x)
    {
        p_l = p;
        split(p->rs, p_l->rs, p_r, x - (getsize(p->ls) + 1));
        p_l->push_up();
    }

    else
    {
        p_r = p;
        split(p->ls, p_l, p_r->ls, x);
        p_r->push_up();
    }
}

void merge(Node *&p, Node *p_l, Node *p_r)
{
    if (!p_l || !p_r)
    {
        p = p_l ? p_l : p_r;
        return;
    }

    p_l->pushD();
    p_r->pushD();

    if (p_l-> rank < p_r-> rank)
    {
        p = p_l;
        merge(p->rs, p_l->rs, p_r);
    }
    else
    {
        p = p_r;
        merge(p->ls, p_l, p_r->ls);
    }

    p->push_up();
}

int top;

Node *newNode(int x)
{
    Node *p = pool + (++top);
    p->val = x;
    p->size = 1;
    p->rank = rand();
    return p;
}

void insert(Node *&p, int x)
{
    Node *p1, *p2;
    split(p, p1, p2, x - 1);
    merge(p, p1, newNode(x));
    merge(p, p, p2);
}

void reverse(Node *&p, int l, int r)
{
    Node *p1, *p2, *p3, *p4;

    split(p, p1, p2, l - 1);
    split(p2, p3, p4, r - l + 1);

    p3->rev ^= 1;

    merge(p2, p3, p4);
    merge(p, p1, p2);
}

int n, m;

void print(Node *p)
{
    p->pushD();

    if (p->ls)
        print(p->ls);
    printf("%d ", p->val);
    if (p->rs)
        print(p->rs);
}

int main()
{
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++)
    {
        insert(root, i);
    }

    while (m--)
    {
        int l, r;
        scanf("%d %d", &l, &r);
        reverse(root, l, r);
    }

    print(root);
    return 0;
}
posted @ 2021-08-17 21:14  lyc_lb  阅读(68)  评论(0)    收藏  举报
-->
查看放大的地图   |   获取路线