●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 ...
随机推荐
- Beta阶段敏捷冲刺报告-DAY4
Beta阶段敏捷冲刺报告-DAY4 Scrum Meeting 敏捷开发日期 2017.11.5 会议时间 11:30 会议地点 羽毛球场 参会人员 全体成员 会议内容 bug的原因讨论, 测试内容安 ...
- Numpy - 多维数组(上)
一.实验说明 numpy 包为 Python 提供了高性能的向量,矩阵以及高阶数据结构.由于它们是由 C 和 Fortran 实现的,所以在操作向量与矩阵时性能非常优越. 1. 环境登录 无需密码自动 ...
- tornado options
tornado.options.define() 用来定义options选项变量的方法,定义的变量可以在全局的tornado.options.options中获取使用,传入参数: name 选项变量名 ...
- docopt——好用的Python命令行参数解释器
Qingchat使用的命令行参数解释器是 docopt,用下来感觉非常棒,所以决定介绍一下这个库.( 奉劝各位看官,真爱生命,远离argparse. ) 介绍 docopt 本质上是在 Python ...
- 九、Python发送QQ邮件(SMTP)
看了廖雪峰老师的教程: 一封电子邮件的旅程就是 发件人 -> MUA -> MTA -> MTA -> 若干个MTA -> MDA <- MUA <- 收件人 ...
- MySQL默认储存引擎修改
1.输入以下SQL语句查看当前储存引擎支持: SHOW ENGINES; 如图所示本机默认引擎为MyISAM: 2.若要修改引擎执行: ALTER TABLE 表名 ENGINE = 储存引擎名: 3 ...
- SQL Server 实现类似C#中 PadLeft功能
USE [Test] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO --@column 表示字段或者常量,@paddingChar 表示 补位 ...
- 作业三:模拟 mysql 进行增删改查
# !/usr/bin/env python3 # _*_coding:utf-8_*_ def help_sql(cmd): if cmd in func_dic.keys(): print('{} ...
- LDAP apacheds解决方案
Apache DS 配置与管理 LADP基本介绍 LDAP(轻量级目录访问协议)以目录的形式来管理资源(域用户,用户组,地址簿,邮件用户,打印机等等). 特点: 1. LDAP是一种网略协议而 ...
- ehcache.xml 属性大全
属性大全 name:缓存名称. maxElementsInMemory:缓存最大个数. eternal:对象是否永久有效,一但设置了,timeout将不起作用. timeToIdleSeconds:设 ...