●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 ...
随机推荐
- 从PRISM开始学WPF(四)Prism-Module?
从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Module? ...
- nyoj 过河问题
过河问题 时间限制:1000 ms | 内存限制:65535 KB 难度:5 描述 在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边.如果不借助手电筒的话,大家是无论如何也不敢过桥去的 ...
- python之路--day10-闭包函数
1.命名关键字参数 格式:在*后面的参数都是命名关键字参数 特点: 1.必须被传值 2.约束函数的调用者必须按照key=value的形式传值 3.约束函数的调用者必须用我们指定的key名 def au ...
- Jenkins 安装、配置与项目新建及构建
1.Jenkins的安装与配置 1.1 java环境配置 Jenkins基于Java, Linux下安装java只要配置java环境变量即可. 首先,解压java到相应目录,我一般习惯把安装的软件放到 ...
- __all__
相信很多人第一次见到这个__all__都很好奇,他有什么作用 那他到底有什么作用呢? 先上代码 from scrapy.utils.reqser import request_to_dict, req ...
- SpringCloud的Hystrix(五) Hystrix机制
参考链接:http://www.jianshu.com/p/e07661b9bae8 一.前言 大型复杂的分布式系统中,高可用相关的技术架构非常重要.高可用架构非常重要的一个环节,就是如何将分布式系统 ...
- j2ee基础(1)servlet的生命周期
Servlet的生命周期 Servlet 生命周期规定了 Servlet 如何被加载.实例化.初始化. 处理客户端请求,以及何时结束服务. 该生命周期可以通过 javax.servlet.Servle ...
- Python 中格式化字符串 % 和 format 两种方法之间的区别
Python2.6引入了 format 格式化字符串的方法,现在格式化字符串有两种方法,就是 % 和 format ,具体这两种方法有什么区别呢?请看以下解析. # 定义一个坐标值 c = (250, ...
- 记录下项目中常用到的JavaScript/JQuery代码一(大量实例)
一直没有系统学习Javascript和Jquery,每次都是用到的时候去搜索引擎查,感觉效率挺低的.这边把我项目中用的的记录下,想到哪写哪,有时间再仔细整理. 当然,由于我主要是写后端java开发,而 ...
- python--socket粘包
socket粘包 1 什么是粘包 须知:只有TCP有粘包现象,UDP永远不会粘包,首先需要掌握一个socket收发消息的原理, 所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少 ...