●赘述题目

四种操作:

○Reset:将整个内存序列清空。

○New a:在尽量靠左的位置新建一个长度为a的内存块,并输出改内存块起始位置。(各个内存块即使相邻也不会合并。。)

○Free a:将a点所在的内存块清空,并输出清空的内存区间的左右端点。

○Get a:输出从左往右数的第a个内存块的起始位置。

●题解

方法:Splay在线维护

(○本来想的将序列中的每个点看作Splay树中的一个节点,然后进行区间操作。。但似乎比较麻烦。。)

○正解(erge大佬提出的思路):考虑到每个内存块不会合并的性质,将每一个内存块看作Splay树中的一个节点,且中序遍历各个节点的顺序即对应内存序列中各个内存块的从左至右的顺序(如下图)(区间化点)。然后剩下便是Splay的单点操作。

○为方便一些操作,先就加入两个边界点。

●代码

(注意NEW(insert)函数啊,有点坑坑。。)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 50005
#define ls tr[k][0]
#define rs tr[k][1]
using namespace std;
int fa[MAXN],tr[MAXN][2];
int l[MAXN],r[MAXN],ll[MAXN],rr[MAXN],ma[MAXN],siz[MAXN];
int tot,root;
void pushup(int k)
{
ll[k]=ls?ll[ls]:l[k]; rr[k]=rs?rr[rs]:r[k];
ma[k]=max(max(ls?ma[ls]:0,rs?ma[rs]:0),max(ls?l[k]-rr[ls]-1:0,rs?ll[rs]-r[k]-1:0));
siz[k]=1+(ls?siz[ls]:0)+(rs?siz[rs]:0);
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y];
int l=tr[y][1]==x,r=1^l;
if(y==k) k=x;
else tr[z][tr[z][1]==y]=x;
fa[tr[x][r]]=y; fa[y]=x; fa[x]=z;
tr[y][l]=tr[x][r]; tr[x][r]=y;
pushup(y);
}
void splay(int x,int &k)
{
int y,z;
while(x!=k)
{
y=fa[x]; z=fa[y];
if(y!=k) ((tr[z][0]==y)^(tr[y][0]==x)) ? rotate(x,k):rotate(y,k);
rotate(x,k);
}
pushup(x);
}
int NEW(int &k,int last,int len,int fg,int sl)
{
if(!k)
{
k=++tot;
fa[k]=last;
l[k]=sl; r[k]=l[k]+len-1;
tr[k][0]=tr[k][1]=0;
splay(k,root);
return l[root];
}
if(fg==0) return NEW(rs,k,len,0,r[k]+1);
else if(fg==1) return NEW(ls,k,len,1,sl);
else if(ls&&ma[ls]>=len) return NEW(ls,k,len,-1,sl);
else if(ls&&l[k]-rr[ls]-1>=len) return NEW(ls,k,len,0,r[k]+1);
else if(rs&&ll[rs]-r[k]-1>=len) return NEW(rs,k,len,1,r[k]+1);
else if(rs&&ma[rs]>=len) return NEW(rs,k,len,-1,sl);
return 0;
}
int find(int k,int x)
{
if(ll[ls]<=x&&x<=rr[ls]) return find(ls,x);
else if(l[k]<=x&&x<=r[k]) return k;
else if(ll[rs]<=x&&x<=rr[rs]) return find(rs,x);
return 0;
}
int FREE(int x)
{
int k=find(root,x);
if(!k) return 0;
splay(k,root);
if(ls*rs==0) root=ls+rs,fa[root]=0;
else
{
int p=rs;
while(tr[p][0]) p=tr[p][0];
tr[p][0]=ls;
fa[ls]=p;
root=rs;
fa[root]=0;
splay(ls,root);
}
return k;
}
int GET(int k,int x)
{
if(siz[ls]>=x) return GET(ls,x); x-=siz[ls];
if(x==1) return l[k]; x-=1;
if(siz[rs]>=x) return GET(rs,x);
return 0;
}
void pre(int n)
{
root=1; tot=2;
tr[1][0]=0; tr[1][1]=2; tr[2][0]=0; tr[2][1]=0;
fa[2]=1;
l[1]=r[1]=0; l[2]=r[2]=n+1;
pushup(2); pushup(1);
}
int main()
{
int n,m,a,b; char s[10];
while(~scanf("%d%d",&n,&m))
{
pre(n);
while(m--)
{
scanf(" %s",s);
if(s[0]=='R') pre(n),printf("Reset Now\n");
else if(s[0]=='N') scanf("%d",&a),1<=a&&a<=n?b=NEW(root,0,a,-1,-1):b=0,b?printf("New at %d\n",b):printf("Reject New\n");
else if(s[0]=='F') scanf("%d",&a),1<=a&&a<=n?b=FREE(a):b=0,b?printf("Free from %d to %d\n",l[b],r[b]):printf("Reject Free\n");
else if(s[0]=='G') scanf("%d",&a),siz[root]-2>=a?b=GET(root,a+1):b=0,b?printf("Get at %d\n",b):printf("Reject Get\n");
}
printf("\n");
}
return 0;
}

●HDU 2871 Memory Control(Splay)的更多相关文章

  1. HDU 2871"Memory Control"(线段树区间和并+set.lower_bound)

    传送门 •题意 有 n 个内存单元(编号从1开始): 给出 4 种操作: (1)Reset :表示把所有的内存清空,然后输出 "Reset Now". (2)New x :表示申请 ...

  2. hdu 2871 Memory Control(伸展树splay tree)

    hdu 2871 Memory Control 题意:就是对一个区间的四种操作,NEW x,占据最左边的连续的x个单元,Free x 把x单元所占的连续区间清空 , Get x 把第x次占据的区间输出 ...

  3. hdu 2871 Memory Control(线段树)

    题目链接:hdu 2871 Memory Control 题目大意:模拟一个内存分配机制. Reset:重置,释放全部空间 New x:申请内存为x的空间,输出左地址 Free x:释放地址x所在的内 ...

  4. HDU 4441 Queue Sequence(splay)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...

  5. hdu 2871 Memory Control (区间合并 连续段的起始位置 点所属段的左右端点)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871 题意: 四种操作: 1.Reset  清空所有内存2.New x  分配一个大小为x的内存块返回,返 ...

  6. HDU 1890 Robotic Sort(splay)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1890 [题意] 给定一个序列,每次将i..P[i]反转,然后输出P[i],P[i]定义为当前数字i ...

  7. HDU 2871 Memory Control

    一共4种操作 其中用线段树 区间合并,来维护连续空的长度,和找出那个位置.其他用vector维护即可 #include<cstring> #include<cstdio> #i ...

  8. HDU 5938 Four Operations(四则运算)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  9. HDU 5775 Bubble Sort(冒泡排序)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

随机推荐

  1. day9

    Alpha冲刺Day9 一:站立式会议 今日安排: 经过为期5天的冲刺,基本完成企业人员模块的开发.因第三方机构与企业存在委托的关系.第三方人员对于风险的自查.风险列表的展示以及自查风险的统计展示(包 ...

  2. C语言——总结回顾

    1.当初你是如何做出选择计算机专业的决定的?经过一个学期,你的看法改变了么,为什么? 你觉得计算机是你喜欢的领域吗,它是你擅长的领域吗? 为什么? 答:①当初选择计算机专业是出于一种选择,是一种带着冲 ...

  3. iOS开发之Objective-C与JavaScript的交互

    UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌入页面中,通过这个方法我们可以在iOS ...

  4. Project facet is Java version 1.7 is not spported

    在移植eclipse项目时,如果遇到 "Project facet Java version 1.7 is not supported." 项目中的jdk1.7不支持.说明项目是其 ...

  5. OpenCASCADE Trihedron Law

    OpenCASCADE Trihedron Law eryar@163.com Abstract. In differential geometry the Frenet-Serret formula ...

  6. 双击CAD对象(具有扩展数据),显示自定义对话框实现方法

    转自:Cad人生 链接:http://www.cnblogs.com/cadlife/p/3463337.html 题目:双击CAD对象,显示自定义对话框实现方法 内容粘贴如下: 主要是绑定两个事件: ...

  7. markdown最基本的几种语法

    1.标题 # 相当于<h1></h1> ## 相当于<h2></h2> ### 相当于<h3></h3> #### 相当于< ...

  8. python 之 列表list && 元组tuple

    目录: 列表 列表基本操作 列表的操作符 列表的函数和方法 元组 介绍: 列表是一种可变的有序集合,可以进行访问.添加和删除操作. 元组是一种不可变的有序集合,可以访问. 1.列表的基本操作 创建列表 ...

  9. es6学习笔记--Interator和Generator(以及for-of的用法)

    这几天学习了遍历器和生成器,看着资料学,有点雾里缭绕的感觉,让人忍不住放弃,还好多看了好几遍,怼着资料里的例子让自己学会了Interator和Generator.   Interator,中文简称:遍 ...

  10. Zepto.js库touch模块代码解析

    Zepto.js也许并不陌生,专门针对移动端开发,Zepto有一些基本的触摸事件可以用来做触摸屏交互(tap事件.swipe事件),Zepto是不支持IE浏览器的. 下面来解析一些Zepto.js触摸 ...