●赘述题目

四种操作:

○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. iOS Storyboard unwind segues使用小结

    使用storyboard开发的时候,经常会在一个scene上添加一个button,再拖拽这个button到某个想要关联的页面,最后选择push的方式跳转.这样scene_A和scene_B就有了一个& ...

  2. visualVM使用jstatd和jmx连接远程jvm及遇到的问题解决

    visualVM使用jstatd和jmx连接远程jvm及遇到的问题解决 JMX方式: 编辑Tomact里bin目录的catalina.sh . 在其头部加入 JAVA_OPTS=" -Dco ...

  3. 第三章Hibernate关联映射

    第三章Hibernate关联映射 一.关联关系 类与类之间最普通的关系就是关联关系,而且关联是有方向的. 以部门和员工为列,一个部门下有多个员工,而一个员工只能属于一个部门,从员工到部门就是多对一关联 ...

  4. maven构建spring报错org.springframework.core.NestedRuntimeException cannot be resolved.

    Error:The type org.springframework.core.NestedRuntimeException cannot be resolved. It is indirectly ...

  5. 前端开发必备之Chrome开发者工具(一)

    本文介绍的 Chrome 开发者工具基于 Chrome 65版本,如果你的 Chrome 开发者工具没有下文提到的那些内容,请检查下 Chrome 的版本 简介 Chrome 开发者工具是一套内置于 ...

  6. linux下git常用命令

    1 安装: sudo apt-get install git 2 创建一个版本库: 新建一个文件夹,进入这个目录之后 git init 3 创建一个版本: git add 文件名或目录 #表示将当前文 ...

  7. Python之面向对象一

    引子 小游戏:人狗大战 角色:人和狗 角色属性:姓名,血量,战斗力和性别(种类) 技能:打/咬 用函数实现人打狗和狗咬人的情形 def Dog(name,blood,aggr,kind): dog = ...

  8. layer ui插件显示tips时,修改字体颜色

    今天做调查问卷,又遇到一个蛋疼小问题,记录下. 调查问卷有很多选项是要求必填的,如果不填的话,需要给出友好的提示.用的如下组件:http://layer.layui.com/ 1.之前一直默认用的: ...

  9. python/ Django之中间件

    python/ Django之中间件 一.中间件 中间件共分为: (1)process_request(self,request) (2)process_view(self, request, cal ...

  10. python json.dumps 中的ensure_ascii 参数引起的中文编码问题

    在使用json.dumps时要注意一个问题   >>> import json >>> print json.dumps('中国') "\u4e2d\u5 ...