题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436

  树状数组做法<猛戳>

  Splay tree的经典题目,有删除和移动操作。首先要离散化各个点,而且对于没有区间还要缩点。对于Top操作,先把目标节点删除,然后移到最左端。Query操作,Splay(tar,0),然后直接访问size。对于Rank操作,通过size产找即可。注意,在每次更新后,都要把处理过的节点都要Splay(tar,0)才能保证复杂度为O(log n),因为这样才能方便下次的访问,因为这个TLE了一个下午+一个晚上。。。。Splay()操作太神了。。

  1. //STATUS:C++_AC_187MS_4196KB
  2. #include <functional>
  3. #include <algorithm>
  4. #include <iostream>
  5. //#include <ext/rope>
  6. #include <fstream>
  7. #include <sstream>
  8. #include <iomanip>
  9. #include <numeric>
  10. #include <cstring>
  11. #include <cassert>
  12. #include <cstdio>
  13. #include <string>
  14. #include <vector>
  15. #include <bitset>
  16. #include <queue>
  17. #include <stack>
  18. #include <cmath>
  19. #include <ctime>
  20. #include <list>
  21. #include <set>
  22. #include <map>
  23. using namespace std;
  24. //using namespace __gnu_cxx;
  25. //define
  26. #define pii pair<int,int>
  27. #define mem(a,b) memset(a,b,sizeof(a))
  28. #define lson l,mid,rt<<1
  29. #define rson mid+1,r,rt<<1|1
  30. #define PI acos(-1.0)
  31. //typedef
  32. typedef __int64 LL;
  33. typedef unsigned __int64 ULL;
  34. //const
  35. const int N=;
  36. const int INF=0x3f3f3f3f;
  37. const int MOD=,STA=;
  38. const LL LNF=1LL<<;
  39. const double EPS=1e-;
  40. const double OO=1e15;
  41. const int dx[]={-,,,};
  42. const int dy[]={,,,-};
  43. const int day[]={,,,,,,,,,,,,};
  44. //Daily Use ...
  45. inline int sign(double x){return (x>EPS)-(x<-EPS);}
  46. template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
  47. template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
  48. template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
  49. template<class T> inline T Min(T a,T b){return a<b?a:b;}
  50. template<class T> inline T Max(T a,T b){return a>b?a:b;}
  51. template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
  52. template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
  53. template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
  54. template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
  55. //End
  56.  
  57. #define Key_value ch[ch[root][1]][0]
  58. int pre[N<<],ch[N<<][]; //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
  59. int sz[N<<],st[N]; //子树规模,内存池
  60. int root,tot,top; //根节点,根节点数量,内存池容量
  61. //题目特定数据
  62. int op[N],cnt[N<<],s[N<<],e[N<<];
  63. int num[N],p[N];
  64. int T,n,m,up;
  65. //debug部分copy from hh
  66. void Treaval(int x) {
  67. if(x) {
  68. Treaval(ch[x][]);
  69. printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d\n",x,ch[x][],ch[x][],pre[x],sz[x]);
  70. Treaval(ch[x][]);
  71. }
  72. }
  73. void debug() {printf("%d\n",root);Treaval(root);}
  74. //以上Debug
  75. //新建一个结点
  76. void NewNode(int &x,int fa,int k,int size)
  77. {
  78. // if(top)x=st[--top];
  79. // else x=++tot;
  80. x=k;
  81. pre[x]=fa;
  82. sz[x]=cnt[x]=size;
  83. ch[x][]=ch[x][]=; //左右孩子为空
  84. }
  85.  
  86. inline void Push_Up(int x)
  87. {
  88. sz[x]=sz[ch[x][]]+sz[ch[x][]]+cnt[x];
  89. }
  90. //旋转,kind为1为右旋,kind为0为左旋
  91. void Rotate(int x,int kind)
  92. {
  93. int y=pre[x],z=pre[y];
  94. //类似SBT,要把其中一个分支先给父节点
  95. ch[y][!kind]=ch[x][kind];
  96. pre[ch[x][kind]]=y;
  97. //如果父节点不是根结点,则要和父节点的父节点连接起来
  98. if(z)ch[z][ch[z][]==y]=x;
  99. pre[x]=z;
  100. ch[x][kind]=y;
  101. pre[y]=x;
  102. Push_Up(y); //维护y结点,不要维护x节点,x节点会再次Push_Down,最后维护一下x节点即可
  103. }
  104. //Splay调整,将根为r的子树调整为goal
  105. void Splay(int x,int goal)
  106. {
  107. int y,z,kind;
  108. while(pre[x]!=goal){
  109. //父节点即是目标位置,goal为0表示,父节点就是根结点
  110. y=pre[x];
  111. if(pre[y]==goal){
  112. Rotate(x,ch[y][]==x);
  113. }
  114. else {
  115. kind=ch[pre[y]][]==y;
  116. //两个方向不同,则先左旋再右旋
  117. if(ch[y][kind]==x){
  118. Rotate(x,!kind);
  119. Rotate(x,kind);
  120. }
  121. //两个方向相同,相同方向连续两次
  122. else {
  123. Rotate(y,kind);
  124. Rotate(x,kind);
  125. }
  126. }
  127. }
  128. //更新根结点
  129. Push_Up(x);
  130. if(goal==)root=x;
  131. }
  132.  
  133. int Get_Min(int x)
  134. {
  135. while(ch[x][])x=ch[x][];
  136. return x;
  137. }
  138. //建树,中间结点先建立,然后分别对区间两端在左右子树建立
  139. void BuildTree(int &x,int l,int r,int fa)
  140. {
  141. if(l>r)return;
  142. int mid=(l+r)>>;
  143. NewNode(x,fa,mid,e[mid]-s[mid]+);
  144. BuildTree(ch[x][],l,mid-,x);
  145. BuildTree(ch[x][],mid+,r,x);
  146. Push_Up(x);
  147. }
  148.  
  149. void Init()
  150. {
  151. root=tot=top=;
  152. ch[][]=ch[][]=pre[]=sz[]=cnt[]=;
  153.  
  154. int i,t,k;
  155. char ss[];
  156. p[]=,t=;
  157. for(i=;i<=m;i++){
  158. scanf("%s%d",ss,&num[i]);
  159. op[i]=ss[]=='T'?:ss[]=='Q'?:;
  160. if(op[i])p[t++]=num[i];
  161. }
  162. sort(p,p+t);
  163. for(k=,i=;i<t;i++)
  164. if(p[i]!=p[k])p[++k]=p[i];
  165. for(i=,up=;i<=k;i++){
  166. if(p[i]-p[i-]>){
  167. s[++up]=p[i-]+;
  168. e[up]=p[i]-;
  169. }
  170. s[++up]=p[i];
  171. e[up]=p[i];
  172. }
  173. if(e[up]!=n){
  174. ++up;
  175. s[up]=e[up-]+;
  176. e[up]=n;
  177. }
  178. BuildTree(root,,up,);
  179. }
  180. //删除编号为x的节点
  181. void Delete(int x)
  182. {
  183. int y=pre[x],s;
  184. if(sz[x]==cnt[x]){
  185. ch[y][ch[y][]==x]=;
  186. s=y;
  187. }
  188. else if(ch[x][]== || ch[x][]==){
  189. s=ch[x][]?ch[x][]:ch[x][];
  190. if(y)ch[y][ch[y][]==x]=s;
  191. pre[s]=y;
  192. }
  193. else {
  194. s=Get_Min(ch[x][]);
  195. Splay(s,x);
  196. if(ch[x][]){
  197. ch[s][]=ch[x][];
  198. pre[ch[x][]]=s;
  199. }
  200. pre[s]=y;
  201. if(y)ch[y][ch[y][]==x]=s;
  202. }
  203. if(y==)root=s;
  204. Splay(s,);
  205. }
  206.  
  207. void Top(int tar)
  208. {
  209. if(sz[root]==cnt[root])return;
  210. Delete(tar);
  211. int x=Get_Min(root);
  212. ch[x][]=tar;
  213. pre[tar]=x;
  214. sz[tar]=cnt[tar];
  215. ch[tar][]=ch[tar][]=;
  216. Splay(tar,);
  217. }
  218.  
  219. int Query(int tar)
  220. {
  221. Splay(tar,);
  222. return sz[ch[root][]]+cnt[tar];
  223. }
  224.  
  225. int Rank(int k)
  226. {
  227. int x=root;
  228. while(){
  229. if(k>sz[ch[x][]] && k<=sz[ch[x][]]+cnt[x]){
  230. k-=sz[ch[x][]];
  231. break;
  232. }
  233. else if(k<=sz[ch[x][]])
  234. x=ch[x][];
  235. else {
  236. k-=sz[ch[x][]]+cnt[x];
  237. x=ch[x][];
  238. }
  239. }
  240. return s[x]+k-;
  241. }
  242.  
  243. int binary(int l,int r,int tar)
  244. {
  245. int mid;
  246. while(l<r){
  247. mid=(l+r)>>;
  248. if(e[mid]<tar)l=mid+;
  249. else if(s[mid]>tar)r=mid;
  250. else return mid;
  251. }
  252. return -;
  253. }
  254.  
  255. int main()
  256. {
  257. // freopen("in.txt","r",stdin);
  258. int i,j,ca=,tar;
  259. scanf("%d",&T);
  260. while(T--)
  261. {
  262. scanf("%d%d",&n,&m);
  263. Init();
  264. printf("Case %d:\n",ca++);
  265. for(i=;i<=m;i++){
  266. if(op[i]){
  267. tar=binary(,up+,num[i]);
  268. if(op[i]==)Top(tar);
  269. else printf("%d\n",Query(tar));
  270. }
  271. else printf("%d\n",Rank(num[i]));
  272. }
  273. }
  274. return ;
  275. }

HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动的更多相关文章

  1. 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay

    正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...

  2. HDU - 1541 Stars 【树状数组】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1541 题意 求每个等级的星星有多少个 当前这个星星的左下角 有多少个 星星 它的等级就是多少 和它同一 ...

  3. HDU 3333 | Codeforces 703D 树状数组、离散化

    HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...

  4. hdu-5493 Queue(二分+树状数组)

    题目链接: Queue Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  5. hdu 4267 多维树状数组

    题意:有一个序列 "1 a b k c" means adding c to each of Ai which satisfies a <= i <= b and (i ...

  6. HDU 4777 Rabbit Kingdom 树状数组

    分析:找到每一个点的左边离他最近的不互质数,记录下标(L数组),右边一样如此(R数组),预处理 这个过程需要分解质因数O(n*sqrt(n)) 然后离线,按照区间右端点排序 然后扫一遍,对于当前拍好顺 ...

  7. HDU 6348 序列计数 (树状数组 + DP)

    序列计数 Time Limit: 4500/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Subm ...

  8. HDU 4325 Flowers(树状数组+离散化)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325 题意:给出n个区间和m个询问,每个询问为一个x,问有多少个区间包含了x. 思路: 因为数据量比较多,所以需 ...

  9. hdu 5775 Bubble Sort 树状数组

    Bubble Sort 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 Description P is a permutation of t ...

随机推荐

  1. 220. Contains Duplicate III

    题目: Given an array of integers, find out whether there are two distinct indices i and j in the array ...

  2. POJ1068——Parencodings

    Parencodings Description Let S = s1 s2...s2n be a well-formed string of parentheses. S can be encode ...

  3. Servlet 下载文件

    这几天有点懒散,还好没有忘记看书,上周去了国家图书馆翻阅了一些和Java相关的书籍,其实这些书都是自己以前看过或者听过,按理来说,不应该看自己已经看过的书籍,应该找一些最新的书籍去看,但是每次走到书架 ...

  4. ARM7ldr指令与ldr伪指令

    ldr伪指令的第二个操作数之前有个=,意思是第一个操作书 = 第二个操作数,相当明了 核心就在于对于用.word指令在.text段里另外定义一段内存,用ldr r0,[pc + x(可以算出.text ...

  5. 基于Android Studio搭建Android应用开发环境

    备注:电脑是windows xp系统 1.     安装JDK和环境变量设置 JDK是java development kit,Java JDK下载地址 http://www.oracle.com/t ...

  6. HashMap和Hashtable的区别(1)

    导读: 1 HashMap不是线程安全的 hastmap实现了map接口,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值.HashMap允许null key和null ...

  7. Java中的volatile

    关于volatile 在JVM 1.2之前,Java的内存模型实现总是从主存读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程环境下 volatile关键字的使用变得非常重要. ...

  8. PostgreSql与sqlserver对比杂记

    PostgreSql与MSSqlServer区别 增删查改没有语法一样. 排序Group Having 聚集函数使用一样 联结查询 ON 子句是最常见的连接条件的类型:它接收一个和 WHERE 子句相 ...

  9. C++ 学习资料搜寻与学习(第一期)(未完待续)

    一.图形图像类 [Visual C++]vs2008/2005正确打开vs2010所创建项目的几种方法 jlins 2012-04-12 14:38 [Visual C++]关于无法打开包括文件:“S ...

  10. Java操作Hbase进行建表、删表以及对数据进行增删改查,条件查询

    1.搭建环境 新建JAVA项目,添加的包有: 有关Hadoop的hadoop-core-0.20.204.0.jar 有关Hbase的hbase-0.90.4.jar.hbase-0.90.4-tes ...