【代码】洛谷P3391 【模板】文艺平衡树(FHQ Treap)
前置知识:
懂 FHQ Treap 模板
仙人指路
解析:
其实没啥难度,直接看代码,该写的都写在注释里了。
//看到这种不是每次操作完都要输出的,都知道是老套路——懒标记
#include<bits/stdc++.h>
using namespace std;#define lc(p) tr[p].ls
#define rc(p) tr[p].rsconst int N = 1e5 + 10;struct node {int ls, rs;int val;int siz;int rev; //懒标记,为 0 的时候不用反转,反之要 int rnd;
} tr[N];
int rt, trlen;int newd(int v) {trlen++;tr[trlen] = {0, 0, v, 1, 0, rand()};return trlen;
}void pushup(int p) {tr[p].siz = tr[lc(p)].siz + tr[rc(p)].siz + 1;
}void pushdown(int p) { //往下懒标记 if (!tr[p].rev) {return ;}swap(lc(p), rc(p));tr[lc(p)].rev ^= 1;tr[rc(p)].rev ^= 1;tr[p].rev = 0;
}//肯定不能按值分割,寻思按位分割
void split(int p, int k, int &x, int &y) {if (p == 0) {x = y = 0;return ;}pushdown(p);if (k > tr[lc(p)].siz) {x = p;split(rc(p), k - tr[lc(p)].siz - 1, rc(x), y);}else {y = p;split(lc(p), k, x, lc(y));}pushup(p);
}int merge(int x, int y) {if ( (!x) || (!y) ) {return x + y;}if (tr[x].rnd < tr[y].rnd) {pushdown(x); //先放懒标记 rc(x) = merge(rc(x), y);pushup(x);return x;}else {pushdown(y);lc(y) = merge(x, lc(y));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].rev ^= 1;rt = merge( x, merge(y, z) );
}void dfs(int p) {if (!p) {return ;}pushdown(p);dfs(lc(p));cout << tr[p].val << " ";dfs(rc(p));
}int main() {ios::sync_with_stdio(false);cin.tie(0);int n, m;cin >> n >> m;rt = trlen = 0;for (int i = 1; i <= n; i++) {rt = merge(rt, newd(i));}for (int i = 1; i <= m; i++) {int l, r;cin >> l >> r;Reverse(l, r);}dfs(rt); //输出之前整体放一遍懒标记 cout << "\n";return 0;
}