初探treap

初探treaptreap 的基本操作 treap 类似二分查找树 只是加了一个堆 用随机值维护平衡 只是期望平衡 小数据下表现并不是特别优秀 但是足够用了 先水两发 之后再继续搞 poj1338UglyN 把质因子只含 2 3 5 的数叫 UglyNumber 通式为 x 2i 3j 5kx 2 i times3 j times5 k 注意到是一个幂次计算 因此大致地有 0 i j k 3

treap的基本操作

poj1338 Ugly Numbers

把质因子只含2,3,5的数叫Ugly Number.通式为:

x=2i×3j×5k



注意到是一个幂次计算,因此大致地有:

0i,j,k30

那么我们只需要枚举 (0i30,x=2,3,5)xi ,然后排序即可。当然也可以直接 logn 地插入,于是可以用 STL set 维护,这里不用set,用Treap维护一下,每个节点还要增加一个 rank ,用来维护子树节点的数量。
代码:

#include 
      #include 
      #include 
      #include 
      #include 
      using namespace std; typedef long long type; struct node { type val; int fix; int rank; //增加维护一个rank值,保存以该节点为根子树的节点数目 node* left; node* right; node() { left = right = NULL; } node(type x) { val = x; fix = rand(); left = right = NULL; } }; inline int rank(node* &T) { return T == NULL ? 0 : T->rank; } void rotate_left(node* &T) { //printf("rotate_left %d\n", T->val); node* tp = T->right; T->right = tp->left; T->rank = rank(T->left) + rank(T->right) + 1; tp->left = T; tp->rank = rank(tp->left) + rank(tp->right) + 1; T = tp; } void rotate_right(node* &T) { //printf("rotate_right %d\n", T->val); node* tp = T->left; T->left = tp->right; T->rank = rank(T->left) + rank(T->right) + 1; tp->right = T; tp->rank = rank(tp->left) + rank(tp->right) + 1; T = tp; } void insert(node* &T, type& val) { if (T == NULL) { T = new node(val); T->rank = 1; } else if (val == T->val) { return; } else if (val < T->val) { insert(T->left, val); ++T->rank; if (T->left->fix < T->fix) { rotate_right(T); } } else { insert(T->right, val); ++T->rank; if (T->right->fix < T->fix) { rotate_left(T); } } } void erase(node* &T, type& val) { if (val == T->val) { if (T->left == NULL || T->right == NULL) { node* t = T; if (T->left == NULL) { T = T->right; } else { T = T->left; } T->rank = rank(T->left) + rank(T->right) + 1; delete t; } else { if (T->left->fix < T->right->fix) { rotate_right(T); erase(T->right, val); } else { rotate_left(T); erase(T->left, val); } } } else if (val < T->val) { erase(T->left, val); --(T->rank); } else { erase(T->right, val); --(T->rank); } } bool exist(node* &T, type val) { if (T == NULL) { return false; } else if (T->val == val) { return true; } else if (val < T->val) { return exist(T->left, val); } else { return exist(T->right, val); } } void clear(node* &T) { if (T == NULL) return; clear(T->left); clear(T->right); delete T; T = NULL; } const type INF = 0xfffffff; type find_k(node* &T, int k) { //printf("find_k(%d)\n", k); if (k <= 0 || k > rank(T)) { return INF; } else if (k == rank(T->left) + 1) { return T->val; } else if (k <= rank(T->left)) { return find_k(T->left, k); } else { return find_k(T->right, k - 1 - rank(T->left)); } } void visit(node* &T) { if (T == NULL) return; visit(T->left); printf("(%d,%d) ", T->val, T->rank); visit(T->right); } const int MAX = 32; type p2[MAX], p3[MAX], p5[MAX]; int main() { p2[0] = p3[0] = p5[0] = 1; for (int i = 1; i < MAX; ++i) { p2[i] = p2[i - 1] << 1; p3[i] = p3[i - 1] * 3; p5[i] = p5[i - 1] * 5; } node* T = NULL; for (int i = 0; i < MAX; ++i) { if (p2[i] <= 0) break; for (int j = 0; j < MAX; ++j) { if (p3[j] <= 0) break; for (int k = 0; k < MAX; ++k) { long long t = p2[i] * p3[j] * p5[k]; if (t <= 0) break; //printf("insert %d\n", t); insert(T, t); } } } //visit(T); //puts(""); int n; while (~scanf(" %d", &n)) { if (n == 0) break; printf("%lld\n", find_k(T, n)); } clear(T); return 0; }

poj1552

这题只需要用到查找操作,遍历维护的 treap ,对任意节点 x 只需要检查是否存在元素

2×x
即可。代码:

#include 
      #include 
      #include 
      #include 
      #include 
      using namespace std; typedef int type; struct node { type val; int fix; node* left; node* right; node() { left = right = NULL; } node(type x) { val = x; fix = rand(); left = right = NULL; } }; void rotate_left(node* &T) { node* tp = T->right; T->right = tp->left; tp->left = T; T = tp; } void rotate_right(node* &T) { node* tp = T->left; T->left = tp->right; tp->right = T; T = tp; } void insert(node* &T, type& val) { if (T == NULL) { T = new node(val); } else if (val <= T->val) { insert(T->left, val); if (T->left->fix < T->fix) { rotate_right(T); } } else { insert(T->right, val); if (T->right->fix < T->fix) { rotate_left(T); } } } void erase(node* &T, type& val) { if (val == T->val) { if (T->left == NULL || T->right == NULL) { node* t = T; if (T->left == NULL) { T = T->right; } else { T = T->left; } delete t; } else { if (T->left->fix < T->right->fix) { rotate_right(T); erase(T->right, val); } else { rotate_left(T); erase(T->left, val); } } } else if (val < T->val) { erase(T->left, val); } else { erase(T->right, val); } } bool exist(node* &T, type val) { if (T == NULL) { return false; } else if (T->val == val) { return true; } else if (val < T->val) { return exist(T->left, val); } else { return exist(T->right, val); } } void clear(node* &T) { if (T == NULL) return; clear(T->left); clear(T->right); delete T; T = NULL; } int query(node* &root, node* &T) { if (T == NULL) return 0; return exist(root, (T->val) * 2) + query(root, T->left) + query(root, T->right); } void visit(node* &T) { if (T == NULL) return; visit(T->left); printf("%d ", T->val); visit(T->right); } int main() { node* T = NULL; int n; while (~scanf(" %d", &n) && n != - 1) { while (n != 0) { insert(T, n); //visit(T); //puts(""); scanf(" %d", &n); } printf("%d\n", query(T, T)); clear(T); } return 0; }

HDU5058 So easy

#include 
      #include 
      #include 
      #include 
      #include 
      using namespace std; typedef int type; struct node { type val; int fix; node* left; node* right; node() { left = right = NULL; } node(type x) { val = x; fix = rand(); left = right = NULL; } }; void rotate_left(node* &T) { node* tp = T->right; T->right = tp->left; tp->left = T; T = tp; } void rotate_right(node* &T) { node* tp = T->left; T->left = tp->right; tp->right = T; T = tp; } void insert(node* &T, type& val) { if (T == NULL) { T = new node(val); } else if (val == T->val) { return; } else if (val < T->val) { insert(T->left, val); if (T->left->fix < T->fix) { rotate_right(T); } } else { insert(T->right, val); if (T->right->fix < T->fix) { rotate_left(T); } } } void erase(node* &T, type& val) { if (val == T->val) { if (T->left == NULL || T->right == NULL) { node* t = T; if (T->left == NULL) { T = T->right; } else { T = T->left; } delete t; } else { if (T->left->fix < T->right->fix) { rotate_right(T); erase(T->right, val); } else { rotate_left(T); erase(T->left, val); } } } else if (val < T->val) { erase(T->left, val); } else { erase(T->right, val); } } bool exist(node* &T, type val) { if (T == NULL) { return false; } else if (T->val == val) { return true; } else if (val < T->val) { return exist(T->left, val); } else { return exist(T->right, val); } } void clear(node* &T) { if (T == NULL) return; clear(T->left); clear(T->right); delete T; T = NULL; } bool query(node* &root, node* &T) { if (T == NULL) return true; return exist(root, T->val) && query(root, T->left) && query(root, T->right); } int main() { int n; type x; node* T1 = NULL, *T2 = NULL; while (~scanf(" %d", &n)) { for (int i = 0; i < n; ++i) { scanf(" %d", &x); insert(T1, x); } for (int i = 0; i < n; ++i) { scanf(" %d", &x); insert(T2, x); } puts(query(T1, T2) && query(T2, T1) ? "YES" : "NO"); clear(T1); clear(T2); } return 0; }




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205363.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午6:12
下一篇 2026年3月19日 下午6:12


相关推荐

  • 旧安卓手机数据转移到新苹果_安卓手机互传数据

    旧安卓手机数据转移到新苹果_安卓手机互传数据如果之前是安卓用户,在购买iPhone12新款手机之后,如何从安卓转移数据到iOS?可以通过苹果官方提供的“转移到iOS”应用,将安卓手机中的内容进行转移,一起来了解一下吧如果之前是安卓用户,在购买iPhone12新款手机之后,如何从安卓转移数据到iOS?可以通过苹果官方提供的“转移到iOS”应用,将安卓手机中的内容进行转移,感兴趣的朋友快来看看吧!如何将数据从安卓设备转移到i…

    2026年1月18日
    3
  • .pkl文件读取_pkl是什么文件格式

    .pkl文件读取_pkl是什么文件格式1.根据网上查阅的读取方法importpicklefile=open(“./dataset-cornell-length10-filter1-vocabSize40000.pkl”,”rb”)data=pickle.load(file)print(data)file.close()在这里,注意在读取的使用的是”rb”,也就是二进制文件格式,而”r”是普通格式的读取用print输…

    2025年10月17日
    8
  • Activity启动模式 及 Intent Flags 与 栈 的关联分析

    Activity启动模式 及 Intent Flags 与 栈 的关联分析在学习 Android 的过程中 Intent 是我们最常用 Android 用于进程内或进程间通信的机制 其底层的通信是以 Binder 机制实现的 在物理层则是通过共享内存的方式实现的 nbsp nbsp Intent 主要用于 2 种情景下 1 发起意图 nbsp 2 广播 nbsp nbsp 它的属性有 ComponentNam action data category extras flags 等 通常情况下 进行 Inten

    2026年3月20日
    2
  • Java 高并发解决方案(电商的秒杀和抢购)

    Java 高并发解决方案(电商的秒杀和抢购)电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要。这次我们会关注秒杀和抢购的技术实现和优化,同时,从技术层面揭开,为什么我们总是不容易抢到火车票的原因? 一、大规模并发带来的挑战 在过去的工作中,我曾经面对过5w每秒的高并发秒杀功能,在这个过程中,整…

    2022年5月31日
    39
  • form表单提交的几种方法

    form表单提交的几种方法form表单提交的几种方法在form标签中添加Action(提交的地址)和method(post),且有一个submit按钮(<inputtype='submit'>)

    2022年7月3日
    26
  • android studio飞机大战游戏带注释源码教程(多线程)[通俗易懂]

    android studio飞机大战游戏带注释源码教程(多线程)[通俗易懂]第一次发博客,学了3天的androidstudio还有一点以前的java基础做了个飞机大战的游戏游戏比较简单大概就这几个功能1.会动的背景2.我的飞机3.发射子弹3.敌人飞机第一步新建一个项目我用的是Android4.4版本新建好项目之后xml文件之类的什么都不用管先新建个类叫做huahua.javapackagecom.dahuijii.liziguo;importandroid.c…

    2022年4月29日
    330

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号