题目
(m) 次区间翻转操作,(1 leq n,m leq 100000)
分析
平衡树模板
于是放上 (fhq-treap) 的板子
(Code)
#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;
const int N = 1e5 + 5;
int n, m, rt;
struct node{
int ls, rs, val, rnd, tag, siz;
}tr[N];
void read(int &x)
{
x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9')
x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
}
void update(int p){tr[p].siz = tr[tr[p].ls].siz + tr[tr[p].rs].siz + 1;}
int new_node(int v)
{
static int tot = 0;
tr[++tot] = node{0, 0, v, rand(), 0, 1};
return tot;
}
int build(int l, int r)
{
if (l > r) return 0;
int mid = (l + r) >> 1, p = new_node(mid);
tr[p].ls = build(l, mid - 1);
tr[p].rs = build(mid + 1, r);
update(p); return p;
}
void pushdown(int p)
{
if (!p || !tr[p].tag) return;
tr[p].tag = 0;
swap(tr[p].ls, tr[p].rs);
if (tr[p].ls) tr[tr[p].ls].tag ^= 1;
if (tr[p].rs) tr[tr[p].rs].tag ^= 1;
}
void split(int p, int k, int &x, int &y)
{
if (!p) x = y = 0;
else{
pushdown(p);
if (k <= tr[tr[p].ls].siz)
y = p, split(tr[p].ls, k, x, tr[p].ls);
else x = p, split(tr[p].rs, k - tr[tr[p].ls].siz - 1, tr[p].rs, y);
update(p);
}
}
int merge(int x, int y)
{
if (!x || !y) return x + y;
pushdown(x), pushdown(y);
if (tr[x].rnd < tr[y].rnd)
{
tr[x].rs = merge(tr[x].rs, y);
update(x); return x;
}
else{
tr[y].ls = merge(x, tr[y].ls);
update(y); return y;
}
}
void dfs(int p)
{
if (!p) return;
pushdown(p);
dfs(tr[p].ls);
printf("%d ", tr[p].val);
dfs(tr[p].rs);
}
void reverse(int l, int r)
{
int a, b, c, d;
split(rt, r, a, b), split(a, l - 1, c, d);
tr[d].tag ^= 1 , rt = merge(merge(c, d), b);
}
int main()
{
srand(time(0));
read(n), read(m);
rt = build(1, n);
for(register int i = 1, l, r; i <= m; i++)
read(l), read(r), reverse(l, r);
dfs(rt);
}