无旋Treap学习笔记

Splay学的头痛,还不知道要怎么用
还是学一学无旋Treap养老比较好,splay能写的也能写,但是常数比较大
依赖随机化大法,复杂度还是比较优秀
主要依靠split分裂操作和merge合并操作来实现各种操作
推荐视频:https://www.bilibili.com/video/av60140850?from=search&seid=2025355617102903408

#include <bits/stdc++.h>
using namespace std;
const int nmax = 1e6 + 7;
const int INF = 0x3f3f3f3f;
struct node {
    int val, rnk, lc, rc, size;
} tree[nmax];
int tot, seed = 233, root = 0;
inline int rrand() {
    return seed = int(seed * 482711ll % 2147483647);
}
inline void update(int rt) {
    tree[rt].size = tree[tree[rt].lc].size + tree[tree[rt].rc].size + 1;
}
int add_node(int val) {
    tree[++tot].size = 1;
    tree[tot].val = val;
    tree[tot].lc = tree[tot].rc = 0;
    tree[tot].rnk = rrand();
    return tot;
}
void split(int rt, int & a, int & b, int val) {
    //a <= val, b > val按值分裂
    if (rt == 0) {
        a = b = 0;
        return;
    }
    if (tree[rt].val <= val) {
        a = rt;
        split(tree[rt].rc, tree[a].rc, b, val);
    } else {
        b = rt;
        split(tree[rt].lc, a, tree[b].lc, val);
    }
    update(rt);
}
void split(int rt, int &a, int &b, int k) {
    //分裂成两个子树,其中左子树大小等于k
    if (rt == 0) {
        a = b = 0;
        return;
    }
    int c = tree[tree[rt].lc].size;
    if (c < k) {
        a  = rt;
        split(tree[rt].rc, tree[rt].rc, b, k - c - 1);
    }
    else {
        b = rt;
        split(tree[rt].lc, a, tree[rt].lc, k);
    }
    update(rt);
}
void merge(int & rt, int a, int b) {
    // 前提:a的权值全部 < b的权值
    if (a == 0 || b == 0) {
        rt = a + b;
        return;
    }
    if (tree[a].rnk < tree[b].rnk) {
        rt = a;
        merge(tree[rt].rc, tree[a].rc, b);
    } else {
        rt = b;
        merge(tree[rt].lc, a, tree[b].lc);
    }
    update(rt);
}
void insert(int & rt, int val) {
    // 插入一个值为val的节点
    int x = 0, y = 0, nnode = add_node(val);
    split(rt, x, y, val);
    merge(x, x, nnode);
    merge(rt, x, y);
}
void delete_node(int & rt, int val) {
    // 删除值为val的节点
    int x = 0, y = 0, z = 0;
    split(rt, x, y, val);
    split(x, x, z, val - 1);
    merge(z, tree[z].lc, tree[z].rc);
    merge(x, x, z);
    merge(rt, x, y);
}
int get_kth(int rt, int k) {
    // 找第k大的数值
    while (tree[tree[rt].lc].size + 1 != k) {
        if (tree[tree[rt].lc].size >= k)
            rt = tree[rt].lc;
        else {
            k -= tree[tree[rt].lc].size + 1;
            rt = tree[rt].rc;
        }
    }
    return tree[rt].val;
}
int get_rank(int & rt, int val) {
    // 查找值对应第几大
    int x = 0, y = 0;
    split(rt, x, y, val - 1);
    int tmp = tree[x].size + 1;
    merge(rt, x, y);
    return tmp;
}
int get_pre(int & rt, int val) {
    // 找值为val的前驱节点数值
    int x = 0, y = 0;
    split(rt, x, y, val - 1);
    int tmp = get_kth(x, tree[x].size);
    merge(rt, x, y);
    return tmp;
}
int get_scc(int & rt, int val) {
    // 找值为val的后继节点数值
    int x = 0, y = 0;
    split(rt, x, y ,val);
    int tmp = get_kth(y, 1);
    merge(rt, x, y);
    return tmp;
}
int n;
int main() {
    scanf("%d", &n);
    int op, val;
    add_node(INF);
    tot = 1;
    tree[1].size = 0;
    root = 1;
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &op, &val);
        if (op == 1) {
            insert(root, val);
        } else if (op == 2) {
            delete_node(root, val);
        } else if (op == 3) {
            printf("%d\n", get_rank(root, val));
        } else if (op == 4) {
            printf("%d\n", get_kth(root, val));
        } else if (op == 5) {
            printf("%d\n", get_pre(root, val));
        } else {
            printf("%d\n", get_scc(root, val));
        }
    }
    return 0;
}

例题:https://www.luogu.org/problem/P3391
每次翻转l-r区间内容,需要给结点打上懒标记,在split和merge里需要子树信息之前就需要pushdown

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
struct fhq_Treap
{
	struct node
	{
		int val, rnk, lc, rc, sz;
		bool lzy;
	} t[maxn];
	int tot = 0, seed = 233, root = 0;
	inline int rrand() {
	    return seed = int(seed * 482711ll % 2147483647);
	}
	inline void pushup(int rt) {
		t[rt].sz = t[t[rt].lc].sz + t[t[rt].rc].sz + 1;
	}
	inline void pushdown(int rt) {
		if (rt && t[rt].lzy)  {
			swap(t[rt].lc, t[rt].rc);
			t[rt].lzy = false;
			t[t[rt].lc].lzy ^= 1;
			t[t[rt].rc].lzy ^= 1;
		}
	}
	int add_node(int val) {
		t[++tot].sz = 1;
		t[tot].val = val;
		t[tot].lc = t[tot].rc = 0;
		t[tot].rnk = rrand();
		t[tot].lzy = false;
		return tot;
	}
	void split(int rt, int &a, int &b, int k) {
	    //分裂成两个子树,其中左子树大小等于k
	    if (rt == 0) {
	        a = b = 0;
	        return;
	    }
	    pushdown(rt);
	    int c = t[t[rt].lc].sz;
	    if (c < k) {
	        a  = rt; 
	        split(t[rt].rc, t[rt].rc, b, k - c - 1);
	    }
	    else {
	        b = rt;
	        split(t[rt].lc, a, t[rt].lc, k);
	    }
	    pushup(rt);
	}
	void merge(int & rt, int a, int b) {
	    // 前提:a的权值全部 < b的权值
	    if (a == 0 || b == 0) {
	        rt = a + b;
	        return;
	    }
	    if (t[a].rnk < t[b].rnk) {
	        rt = a; pushdown(rt);
	        merge(t[rt].rc, t[a].rc, b);
	    } else {
	        rt = b; pushdown(rt);
	        merge(t[rt].lc, a, t[b].lc);
	    }
	    pushup(rt);
	}
	void reverse(int l, int r) {
		int x = 0, y = 0, z = 0;
		split(root, x, y, l - 1);
		split(y, y, z, r - l + 1);
		t[y].lzy ^= 1;
		merge(y, x, y);
		merge(root, y, z);
	}
	bool output_flg = true;
	void output(int rt) {
		if (!rt) return;
		pushdown(rt);
		output(t[rt].lc);
		if (output_flg) output_flg = false, printf("%d", t[rt].val);
		else printf(" %d", t[rt].val);
		output(t[rt].rc);
	}
} tep;
int main()
{
	freopen("in.txt", "r", stdin);
	int n, m; scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		tep.merge(tep.root, tep.root, tep.add_node(i));
	}
	while (m--) {
		int l, r; scanf("%d%d", &l, &r);
		tep.reverse(l, r);
	}
	tep.output(tep.root);
	putchar('\n');
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值