文艺平衡树
【模板】文艺平衡树
题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列。 其中需要提供以下操作:翻转一个区间,例如原有序序列是 $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;
}

浙公网安备 33010602011771号