文藝平衡樹(Fhq Treap)

傳送門:文藝平衡樹
首先要闡述一點,Fhq Treap的按大小分裂是支持區間操作的,而按值分裂是不支持區間操作的。
Fhq Treap的分裂方式:

  • 按權值分裂
  • 按大小分裂

按權值分裂:

根據插入點的權值,將樹按w爲邊界,分裂爲兩顆樹,一顆樹的權值大於w,一棵樹的權值小於等於w,這樣再把新節點合並進去,就可以維護樹的平衡

按大小分裂:

根據插入點的節點大小,將樹按big爲邊界,分裂爲兩顆樹,一顆樹的節點大小大於big,一棵樹的節點大小小於等於big,這樣再把新節點合並進去,不僅可以維護樹的平衡,還支持區間操作

爲什麼按大小分裂會支持區間操作:

首先,新開的每一個節點,都可以用節點數量,代表區間中的一個端點,呢麼我們如果修改區間,呢麼我們只需要修改平衡樹中節點數量在我們要修改的區間內即可,然後合併成新的平衡樹即可,一顆平衡樹的節點對應數量是一樣的,我們只需要改變節點對應的值即可

該題思路:

利用支持區間修改的Fhq Treap,我們利用懶惰標記,對區間進行修改,交換當前區間的左右子樹,從而達到顛倒一個區間

:隨機庫函數,好多版本的C++不支持,所以就自己寫一個叭

參考代碼:

#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <map>
#include <queue>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <set>
using namespace std;
const int inf = (1 << 30);
typedef long long ll;
const int base = 131;
const int maxn = 1e5 + 5;
//vector<ll> vec;
//ll n, sum[maxn * 10], c[maxn * 10], a[maxn];
//vector<int> vec;
int su = 1;
int rand()
{
    su = (su * base) % 1000007;
    return su;
}
int cnt, rt;
struct node
{
    int ls, rs, w;
    int key, sizx;
    int lazy;
} tr[maxn*50];
int newnode(int w)
{
    tr[++cnt].w = w, tr[cnt].sizx = 1;
    tr[cnt].lazy=0;
    tr[cnt].key = rand();
    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 big, int &x, int &y)
{
    if (!now)
        x = y = 0;
    else
    {
        pushdown(now);
        if (tr[tr[now].ls].sizx < big)
            x = now, split(tr[now].rs, big - tr[tr[now].ls].sizx - 1, tr[now].rs, y);
        else
            y = now, split(tr[now].ls, big, x, tr[now].ls);
        pushup(now);
    }
}
int merge(int x, int y)
{
    if (!x || !y)
        return x + y;
    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(merge(x, 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, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        rt = merge(rt, newnode(i));
    }
    while (m--)
    {
        int ql, qr;
        cin >> ql >> qr;
        reverse(ql, qr);
    }
    dfs(rt);
    cout<<endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章