●HDU 2871 Memory Control(Splay)
●赘述题目
四种操作:
○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)的更多相关文章
- HDU 2871"Memory Control"(线段树区间和并+set.lower_bound)
传送门 •题意 有 n 个内存单元(编号从1开始): 给出 4 种操作: (1)Reset :表示把所有的内存清空,然后输出 "Reset Now". (2)New x :表示申请 ...
- hdu 2871 Memory Control(伸展树splay tree)
hdu 2871 Memory Control 题意:就是对一个区间的四种操作,NEW x,占据最左边的连续的x个单元,Free x 把x单元所占的连续区间清空 , Get x 把第x次占据的区间输出 ...
- hdu 2871 Memory Control(线段树)
题目链接:hdu 2871 Memory Control 题目大意:模拟一个内存分配机制. Reset:重置,释放全部空间 New x:申请内存为x的空间,输出左地址 Free x:释放地址x所在的内 ...
- HDU 4441 Queue Sequence(splay)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...
- hdu 2871 Memory Control (区间合并 连续段的起始位置 点所属段的左右端点)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871 题意: 四种操作: 1.Reset 清空所有内存2.New x 分配一个大小为x的内存块返回,返 ...
- HDU 1890 Robotic Sort(splay)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1890 [题意] 给定一个序列,每次将i..P[i]反转,然后输出P[i],P[i]定义为当前数字i ...
- HDU 2871 Memory Control
一共4种操作 其中用线段树 区间合并,来维护连续空的长度,和找出那个位置.其他用vector维护即可 #include<cstring> #include<cstdio> #i ...
- HDU 5938 Four Operations(四则运算)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- HDU 5775 Bubble Sort(冒泡排序)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
随机推荐
- 结对编程作业——四则运算GUI程序
毛忠庆 201421122088 赵嘉楠 201421122065 源代码存放位置:https://gitee.com/ouwen0819/SiZeYunSuan.git 题目描述 使用 -n 参数控 ...
- 搭建java环境——使用Sublime Text 3(windows环境)
实现sublime Text 3对Java编译执行 参考网址:http://tieba.baidu.com/p/2609515186 1.1直接在安装路径下找到*\Packages\Java.subl ...
- 织梦dedecms默认网站地图sitemap.html优化
网站地图对于网站优化很重要,搜索引擎就是靠网站地图去收录网站页面,本文主要讲解优化织梦自带的网站地图功能. 织梦自带的网站地图使用方法:织梦后台--生成--HTML更新--更新网站地图,可以在 ...
- django启动uwsgi报错
查看uwsgi.log *** Starting uWSGI 2.0.17 (64bit) on [Thu Apr 5 17:46:15 2018] *** compiled with version ...
- MSIL实用指南-生成接口
本篇讲解怎么样生成接口,即interface. 一.创建类型创建一个接口类型依旧用ModuleBuilder的DefineType方法,但是它的第二个参数必须要有TypeAttributes.Inte ...
- IntelliJ IDEA sass环境配置及常见报错处理
1.下载安装ruby,网上教程很多的,安装完之后在命令行输入ruby -v检查一下是否安装成功了.(注意安装的时候要勾选第二项).
- vue组件详解(五)——组件高级用法
一.递归组件 组件在它的模板内可以递归地调用自己, 只要给组件设置name 的选项就可以了. 示例如下: <div id="app19"> <my-compone ...
- Django--ORM基本操作
一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 pr ...
- spark分区数,task数目,core数,worker节点个数,excutor数量梳理
作者:王燚光链接:https://www.zhihu.com/question/33270495/answer/93424104来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- Android:触屏事件
Android触屏事件包含两种: 1)屏幕触屏事件:重写onTouchEvent(MotionEvent event): 2)控件触屏事件:给控件注册触屏事件,setOnTouchEventListe ...