之前学了FHQ-Treap 但是很生疏,今天就完全自己码一发,熟悉熟悉,调调bug,,熟悉一下代码里面的各种细节问题。
因为FHQ-Treap 要实现区间操作,是不能按值分裂的,需要按节点大小分裂,这样我们只需要将节点大小为[l,r]区间的这颗树分解出来,然后进行修改即可。
文艺平衡树,是要颠倒 q 次的询问区间,最后输出整个区间,试想一下,如果朴素写法绝对复杂度爆炸,所以用 FHQ-Treap 的操作就很 l o g log log 了,虽然常数有点大,但不是问题。
讲一下思路(菜鸡的小思路):
分裂出包含 [l,r] 区间的平衡树,对这颗树打上标记,交换左右儿子节点即可,然后合并回整颗平衡树,在合并的时候,下传标记即可。
参考代码:
#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long ll;
const int inf = 1 << 30;
const int maxn = 2e5 + 5;
const int N = 1e3 + 5;
const int base = 131;
struct node
{
int ls, rs, sizx, w, lazy, key;
} tr[maxn];
int su = 1, cnt, rt;
int rand()
{
su = (su * base) % 1000007;
return su;
}
int newnode(int w)
{
tr[++cnt].w = w, tr[cnt].key = rand();
tr[cnt].sizx = 1, tr[cnt].lazy = 0;
return cnt;
}
void pushup(int now)
{
tr[now].sizx = tr[tr[now].ls].sizx + tr[tr[now].rs].sizx + 1;
}
void pushdown(int now)
{
if (tr[now].lazy)
{
swap(tr[now].ls, tr[now].rs);
tr[tr[now].ls].lazy ^= 1, tr[tr[now].rs].lazy ^= 1;
tr[now].lazy = 0;
}
}
void split(int now, int mid, int &x, int &y)
{
if (!now)
x = y = 0;
else
{
pushdown(now);
if (mid <= tr[tr[now].ls].sizx)
{
y = now, split(tr[now].ls, mid, x, tr[now].ls);
}
else
{
x = now, split(tr[now].rs, mid - tr[tr[now].ls].sizx - 1, tr[now].rs, y);
}
pushup(now);
}
}
int merge(int x, int y)
{
if (!x || !y)
return x + y;
else
{
if (tr[x].key > tr[y].key)
{
pushdown(x);
tr[x].rs = merge(tr[x].rs, y);
pushup(x);
return x;
}
else
{
pushdown(y);
tr[y].ls = merge(x, tr[y].ls);
pushup(y);
return y;
}
}
}
void reverse(int l, int r)
{
int x, y, z;
split(rt, l - 1, x, y);
split(y, r - l + 1, y, z);
tr[y].lazy ^= 1;
rt = merge(x, merge(y, z));
}
void dfs(int now)
{
if (!now)
return;
pushdown(now);
dfs(tr[now].ls);
cout << tr[now].w << ' ';
dfs(tr[now].rs);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++)
rt = merge(rt, newnode(i));
while (q--)
{
int ql, qr;
cin >> ql >> qr;
reverse(ql, qr);
}
dfs(rt);
}
// PAYPALISHIRING"
// 7
// 1,8,6,2,5,4,8,3,7
// 5 3
// 1 3
// 1 3
// 1 4
// 4 3 2 1 5