什么叫tnd的优雅?这tnd的就是优雅!
普通的treap如果遇到区间序列问题就没办法了
比如这道splay的模板题,根本没法做。
但是总会有神仙让他可以做!
我们现在不需要insert和del了,因为都是针对单点维护的操作。
我们要学会区间insert和区间del!
split(int rt, int k, int &x, int &y)
将一整棵树分成两棵树,k就是划分的依据,我们可以根据需求将权值小于k的划分到一棵树,权值
大于k的划分到另外一棵树。也可以把前k个划分到一棵树,剩下的划分到另外一棵树。
具体的操作就是根据二叉排序树的特性,假设要分成x,y两棵树,约定x为的权值或序列小的一边。
如果当前节点的权值大于k(按权值划分)或者左子树的节点数大于k(按序列划分)那么当前节点肯定是属于y树的反之就是x树。这个时候我们只需要考虑x与y的左子树的关系了(结合二叉树的特性想一想为什么),反之只需要考虑x的右子树和y的关系。
merge(int A, int B)
将A,B两棵树合并成一棵树。
结合的时候要考虑到二叉树的左>中>右的特性,的话我们只有两种可能的合并方式,但是别忘了treap是有随机权的,这样可以让我们的树更扁
一点。所以我们可以让权重大的在上。。。
如果你没听懂,推荐一个我看的博客。
可能有配图要容易理解的多。
#pragma GCC optimize(2)
#include
using namespace std;
const int maxn = 1e6+5;
typedef long long ll;
const ll mod = 1e9+7;
int Case = 1;
int n, m;
struct Random {
int sed, A, C, M;
Random(int sed = rand(), int A = 48271, int C = 57, int M = 2147483647)
: sed(sed), A(A), C(C), M(M) {}
int out() { return (sed = ((A * sed + C) % M)); }
} A;
struct Treap{
int ch[maxn][2], val[maxn];
int dat[maxn], size[maxn], flag[maxn];
int root, tot;
int newnode(int v) {
val[++tot] = v;
dat[tot] = A.out();
size[tot] = 1;
return tot;
}
void pushup(int rt) {
size[rt] = 1 + size[ch[rt][0]] + size[ch[rt][1]];
}
void pushdown(int rt) {
if(flag[rt]) {
swap(ch[rt][0], ch[rt][1]);
if(ch[rt][0]) flag[ch[rt][0]] ^= 1;
if(ch[rt][1]) flag[ch[rt][1]] ^= 1;
flag[rt] = 0;
}
}
void split(int rt, int k, int &x, int &y) {
if(!rt) x = y = 0;
else {
pushdown(rt);
if(k <= size[ch[rt][0]]) {
y = rt;
split(ch[rt][0], k, x, ch[rt][0]);
}
else {
x = rt;
split(ch[rt][1], k-size[ch[rt][0]]-1, ch[rt][1], y);
}
pushup(rt);
}
}
int merge(int A, int B) {
if(!A || !B) return A + B;
if(dat[A] < dat[B]) {
pushdown(A);
ch[A][1] = merge(ch[A][1], B);
pushup(A);
return A;
}
else {
pushdown(B);
ch[B][0] = merge(A, ch[B][0]);
pushup(B);
return B;
}
}
void dfs(int rt) {
if(!rt) return;
pushdown(rt);
dfs(ch[rt][0]);
printf("%d ", val[rt]);
dfs(ch[rt][1]);
}
}treap;
void solve() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
treap.root = treap.merge(treap.root, treap.newnode(i));
}
for(int i = 1; i <= m; i++) {
int l, r, a, b, c;
scanf("%d%d", &l, &r);
treap.split(treap.root, l-1, a, b);
treap.split(b, r-l+1, b, c);
treap.flag[b] ^= 1;
treap.root = treap.merge(a, treap.merge(b, c));
}
treap.dfs(treap.root);
return;
}
int main() {
srand(time(0));
//g++ -std=c++11 -o2 1.cpp -o f && ./f < in.txt
//ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
while(Case--) {
solve();
}
return 0;
}