Problem 平衡树 Splay

题目大意

  维护一个数列,支持三种操作。

  操作1:添加一个数x。

  操作2:询问不超过x的最大的数。

  操作三:删除大小在区间【a,b】内的数。

解题分析

  和上一题相比,多了一个删除的操作。

  首先将a的前驱节点x旋转到根,然后将b的后驱节点y旋转到x的右孩子,这样所有大小在【a,b】内的数均位于y的左子树内,直接将其删掉就可以了。

  为了防止找不到x和y,在初始化时向树中插入一个极大值和一个极小值。

参考程序

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. struct node{
  5. int val;
  6. node *left,*right,*father;
  7. node(int val_=,node* father_=NULL,node* left_=NULL,node* right_=NULL)
  8. {
  9. val=val_; father=father_; left=left_; right=right_;
  10. }
  11. }*rt,*t1,*t2;
  12.  
  13. void search(node *now)
  14. {
  15. cout<<now<<" "<<now->val<<" "<<now->left<<" "<<now->right<<" "<<now->father<<endl;
  16. if (now->left) search(now->left);
  17. if (now->right) search(now->right);
  18. }
  19.  
  20. void pushup(node *x)
  21. {
  22. }
  23.  
  24. void right(node* x,node* &rt)
  25. {
  26. node *y=x->father,*z=y->father;
  27. if (y==rt) rt=x;
  28. else if (z->left==y) z->left=x; else z->right=x; //需要判断是左右孩子
  29. x->father=z; y->father=x; if (x->right) x->right->father=y; //防止对空指针进行操作
  30. y->left=x->right; x->right=y;
  31. pushup(y); pushup(x);
  32. }
  33.  
  34. void left(node* x,node* &rt)
  35. {
  36. node *y=x->father,*z=y->father;
  37. if (y==rt) rt=x;
  38. else if (z->left==y) z->left=x; else z->right=x;
  39. x->father=z; y->father=x; if (x->left) x->left->father=y;
  40. y->right=x->left; x->left=y;
  41. pushup(y); pushup(x);
  42. }
  43.  
  44. void splay(node* x,node* &rt)
  45. {
  46. while (x!=rt)
  47. {
  48. node *y=x->father, *z=y->father;
  49. if (y==rt)
  50. {
  51. if (x==y->left) right(x,rt);
  52. else left(x,rt);
  53. }
  54. else
  55. {
  56. if (y==z->left)
  57. if (x==y->left) { right(y,rt); right(x,rt); }
  58. else { left(x,rt); right(x,rt); }
  59. else
  60. if (x==y->right) { left(y,rt); left(x,rt); }
  61. else { right(x,rt); left(x,rt); }
  62. }
  63. }
  64. }
  65.  
  66. void insert(int val,node* &now,node *last)
  67. {
  68. if (now==NULL)
  69. {
  70. now=new node(val,last);
  71. splay(now,rt);
  72. return;
  73. }
  74. if (val < now->val) insert(val,now->left,now); else //else还是要加的 返回的时候树的形态已经改变了
  75. if (val > now->val) insert(val,now->right,now);
  76. }
  77.  
  78. int get(int val,node *x)
  79. {
  80. int res=-<<;
  81. while (x!=NULL)
  82. {
  83. if (x->val>val) x=x->left;
  84. else
  85. {
  86. res=max(res,x->val);
  87. x=x->right;
  88. }
  89. }
  90. return res;
  91. }
  92.  
  93. void find_1(int val,node *x)
  94. {
  95. if (x==NULL) return;
  96. if (x->val>=val) find_1(val,x->left);
  97. else {t1=x; find_1(val,x->right);}
  98. }
  99.  
  100. void find_2(int val,node *x)
  101. {
  102. if (x==NULL) return;
  103. if (x->val<=val) find_2(val,x->right);
  104. else {t2=x; find_2(val,x->left);}
  105. }
  106.  
  107. void work(int l,int r)
  108. {
  109. t1=t2=NULL;
  110. find_1(l,rt); splay(t1,rt);
  111. find_2(r,rt->right); splay(t2,rt->right);
  112. rt->right->left=NULL;
  113. }
  114.  
  115. int main()
  116. {
  117. int n;
  118. rt=NULL;
  119. scanf("%d",&n);
  120. insert(<<,rt,NULL); insert(-<<,rt,NULL);
  121. for (int i=;i<=n;i++)
  122. {
  123. char s[]; int x,y;
  124. scanf("%s%d",s,&x);
  125. if (s[]=='I') insert(x,rt,NULL);
  126. if (s[]=='Q') cout<<get(x,rt)<<endl;
  127. if (s[]=='D')
  128. {
  129. scanf("%d",&y);
  130. if (x>y) swap(x,y);
  131. work(x,y);
  132. }
  133. }
  134. }

Hihocoder 1329(splay)的更多相关文章

  1. Hihocoder 1325 (splay)

    Problem 平衡树 Treap 题目大意 维护一个数列,支持两种操作. 操作1:添加一个数x. 操作2:询问不超过x的最大的数. 解题分析 尝试了一下用指针来写splay,感觉写起来还是比较流畅的 ...

  2. Hihocoder 1333 (splay)

    Problem 平衡树 splay2 题目大意 维护一个序列,支持四种操作: 操作1:添加一个数,编号为x,权值为y. 操作2:删除编号在区间[x,y]内的数. 操作3:将编号在区间[x,y]内的数的 ...

  3. Hihocoder 1329 平衡树·Splay(平衡树)

    Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...

  4. 【BZOJ3506】排序机械臂(Splay)

    [BZOJ3506]排序机械臂(Splay) 题面 神TMBZOJ没有题面,感谢SYC的题面 洛谷的题面也不错 题解 对于每次旋转的物体 显然可以预处理出来 现在只要模拟旋转操作就行了 至于在哪里放标 ...

  5. 【BZOJ1500】【NOI2005】维修数列(Splay)

    [BZOJ1500][NOI2005]维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream ...

  6. 【BZOJ1862】[ZJOI2006]游戏排名系统 (Splay)

    [BZOJ1862][ZJOI2006]游戏排名系统 (Splay) 题面 BZOJ 洛谷 题解 双倍经验题

  7. 【BZOJ1056】[HAOI2008]排名系统(Splay)

    [BZOJ1056][HAOI2008]排名系统(Splay) 题面 BZOJ 洛谷 题解 \(Splay\)随便维护一下就好了,至于名字什么的,我懒得手写哈希表了,直接哈希之后拿\(map\)压. ...

  8. 【BZOJ2329】括号修复(Splay)

    [BZOJ2329]括号修复(Splay) 题面 BZOJ 洛谷 题解 本来想着用线段树来写 但是有一个区间翻转 所以不能用线段树了,就只能用平衡树 然后直接\(Splay\)就好了 注意一下几个标记 ...

  9. P3391 【模板】文艺平衡树(Splay)新板子

    P3391 [模板]文艺平衡树(Splay) 题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转 ...

随机推荐

  1. (博弈论)51NOD 1066 Bash游戏

    有一堆石子共有N个.A B两个人轮流拿,A先拿.每次最少拿1颗,最多拿K颗,拿到最后1颗石子的人获胜.假设A B都非常聪明,拿石子的过程中不会出现失误.给出N和K,问最后谁能赢得比赛. 例如N = 3 ...

  2. 使用Redis存储Nginx+Tomcat负载均衡集群的Session

    配置Tomcat的session共享可以有三种解决方案: 第一种是以负载均衡服务器本身提供的session共享策略,每种服务期的配置是不一样的并且nginx本身是没有的. 第二种是利用web容器本身的 ...

  3. PHP定义字符串时单引号和双引号的区别

    一般用单引号或双引号标识一个字符串.单引号串与双引号串,在PHP中的处理是不同的.双引号中的内容可以被解释并被替换,单引号串中的内容则被作为普通字符处理. 例如: $str=6; echo " ...

  4. 238 Product of Array Except Self 除自身以外数组的乘积

    一个长度为 n 的整形数组nums,其中 n > 1,返回一个数组 output ,其中 output[i] 等于nums中除nums[i]以外所有元素的乘积.不用除法 且在O(n)内解决这个问 ...

  5. [转]深入ASP.NET MVC之二:路由模块如何工作

    本文转自:http://www.cnblogs.com/yinzixin/archive/2012/11/05/2754483.html 摘要: 上文分析了UrlRouting模块何时会被触发,本文重 ...

  6. [转]MVC4项目中验证用户登录一个特性就搞定

    本文转自:http://www.mrhuo.com/Article/Details/470/A-Attribute-For-MVC4-Project-Used-To-Validate-User-Log ...

  7. .net面试题 2016

    经典面试题2016——50题 1.面向对象语言具有——继承性——,——封装性——,——多态性—— 继承性:就是让一个类型的对象拥有另一个类型的对象的属性的方法.继承后,子类拥有父类的属性和方法. 封装 ...

  8. Flask Web 发送邮件单文件

    import os from flask import Flask, render_template, session, redirect, url_for from flask_script imp ...

  9. struts2之通配符映射

    系统有n多个请求时候,不可能以一个action对应一个映射.可以用通配符映射将成百上千请求简化成一个通用映射. 通配符映射规则:1.若找到多个匹配,没有通配符的将胜出. 2.若指定的动作不存在,str ...

  10. 在Resource中使用x:Bind

    Build2015上,MS热情高涨的演示了x:Bind,一种新的Binding方式,新的方式有如下优点: 1更好的性能(内存占用,CPU占用) 2BuildTime的Binding 具体在Channe ...