其他分享
首页 > 其他分享> > 文艺平衡树

文艺平衡树

作者:互联网

# 【模板】文艺平衡树

## 题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列。

其中需要提供以下操作:翻转一个区间,例如原有序序列是 5 4 3 2 1,翻转区间是 [2,4] 的话,结果是 5 2 3 4 1。

## 输入格式

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

## 输出格式

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

 

题意:维护区间信息,每次会选择一个区间,翻转这个区间,最后输出区间的信息

做法:splay,FHGtreap

 

FHGtreap做法

要翻转l~r区间,就是先打上标记,然后再下传懒标记,首先把整棵树按树的大小分裂成x(1~l - 1), z(l~n), 再将z树分裂成y(l~r), z(r + 1, n),这个时候得到的y树就是整个要操作的区间,最后别忘了把x, y, z树合并返回根节点

#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
#include <set>
#include <map>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

#define x first
#define y second

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<PII, int> PIII;
typedef pair<LL, LL> PLL;
const int N = 100010, M = 50000, mod = 998244353, INF = 0x3f3f3f3f, P = 1e8 - 3;

struct tree{
    int l, r;
    int val, key;
    int lazy, sz;
}tr[N];
int root, cnt;
int l, r;

int newNode(int val)
{
    tr[++ cnt].val = val;
    tr[cnt].key = rand();
    tr[cnt].sz = 1;
    return cnt;
}

void update(int now)
{
    tr[now].sz = tr[tr[now].l].sz + tr[tr[now].r].sz + 1;
}

void pushdown(int now)
{
    swap(tr[now].l, tr[now].r);
    tr[tr[now].l].lazy ^= 1;
    tr[tr[now].r].lazy ^= 1;
    tr[now].lazy = 0;
}

int x, y, z;

//按树的大小分裂 void spilt(int now, int sz, int &x, int &y) { if(!now) x = y = 0; else { if(tr[now].lazy) pushdown(now);//每次可能改变树的结构的操作前都要将懒标记下传 if(tr[tr[now].l].sz < sz) { x = now; spilt(tr[x].r, sz - tr[tr[now].l].sz - 1, tr[x].r, y); } else { y = now; spilt(tr[y].l, sz, x, tr[y].l); } update(now); } } int merge(int x, int y) { if(!x || !y) return x + y; else { if(tr[x].key > tr[y].key) { if(tr[x].lazy) pushdown(x); tr[x].r = merge(tr[x].r, y); update(x); return x; } else { if(tr[y].lazy) pushdown(y); tr[y].l = merge(x, tr[y].l); update(y); return y; } } } void ldr(int now) //输出中序遍历 { if(!now) return; if(tr[now].lazy) pushdown(now);//别忘了将剩下的懒标记下传 ldr(tr[now].l); printf("%d ", tr[now].val); ldr(tr[now].r); } void reverse(int l, int r) { spilt(root, l - 1, x, z); spilt(z, r - l + 1, y, z); tr[y].lazy ^= 1; merge(merge(x, y), z); } int main() { int n, m; scanf("%d %d", &n, &m); for(int i = 1; i <= n; i ++ ) root = merge(root, newNode(i)); while(m -- ) { scanf("%d %d", &l, &r); reverse(l, r); } ldr(root); return 0; }

 

splay:

把节点l转到根节点,再把r转到l的下面,这个时候节点r的左子树就是要操作的区间的子树,打上懒标记即可

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100010;

struct Node{
    int s[2], p, v;
    int sz, lazy;
    
    void init(int _v, int _p){
        v = _v, p = _p;
        sz = 1;
    }
}tr[N];
int root, idx;
int n, m;

void pushup(int u)
{
    tr[u].sz = tr[tr[u].s[0]].sz + tr[tr[u].s[1]].sz + 1;
}

void pushdown(int u)
{
    if(tr[u].lazy)
    {
        swap(tr[u].s[0], tr[u].s[1]);
        tr[tr[u].s[0]].lazy ^= 1;
        tr[tr[u].s[1]].lazy ^= 1;
        tr[u].lazy = 0;
    }
}

//左右旋 void rotate(int x) { int y = tr[x].p, z = tr[y].p; int k = tr[y].s[1] == x; tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z; tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y; tr[x].s[k ^ 1] = y, tr[y].p = x; pushup(y), pushup(x); } void splay(int x, int k) { while(tr[x].p != k) { int y = tr[x].p, z = tr[y].p; if(z != k) if((tr[z].s[1] == y) ^ (tr[y].s[1] == x)) rotate(x); else rotate(y); rotate(x); } if(!k) root = x; } void insert(int v) { int u = root, p = 0; while(u) p = u, u = tr[u].s[v > tr[p].v]; u = ++ idx; if(p) tr[p].s[v > tr[p].v] = u; tr[u].init(v, p); splay(u, 0); } int get_k(int k) { int u = root; while(u) { pushdown(u); if(tr[tr[u].s[0]].sz >= k) u = tr[u].s[0]; else if(tr[tr[u].s[0]].sz + 1 == k) return u; else k -= tr[tr[u].s[0]].sz + 1, u = tr[u].s[1]; } return -1; } void ldr(int u) { if(!u) return; pushdown(u); ldr(tr[u].s[0]); if(tr[u].v >= 1 && tr[u].v <= n) printf("%d ", tr[u].v); ldr(tr[u].s[1]); } int main() { cin >> n >> m; for(int i = 0; i <= n + 1; i ++ ) insert(i); while(m -- ) { int l, r; cin >> l >> r; l = get_k(l), r = get_k(r + 2); splay(l, 0), splay(r, l); tr[tr[r].s[0]].lazy ^= 1; } ldr(root); return 0; }

 

标签:sz,lazy,include,int,tr,文艺,平衡,now
来源: https://www.cnblogs.com/jay1573/p/16622916.html