YBTOJ内存管理(堆的应用)
时间:2021-09-13
本文章向大家介绍YBTOJ内存管理(堆的应用),主要包括YBTOJ内存管理(堆的应用)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题面
题目分析
这题最大的特点就是细节很多,注意审题。
(1)如果被占用,则必须过600s(包括当前这一秒)才能恢复空的状态。
而如果这期间内存被查询了,则需要再过600s才能被再次使用。
(2)如果一个内存没有被占用,则查询不会将它变为占用的状态。
(3)发出占用一个内存的请求时,优先占用编号最小的内存点。
算法设计:
写两个小根堆,第一个堆heap1存储未被占用的点的编号,第二堆heap2存储被占用的点开始被占用的时间。
每次输入得到一个当前时间n,则不断地取出heap2的堆顶,若堆顶已经不再被占用,则将其插入heap1中,直到出现一个仍被占用的点,则循环结束。
然后再判断要求的操作,若为请求占用空间,则取出heap1堆顶,插入heap2中,若为判断,则用vis数组处理。
然后就会发现我们忘记了一个问题:
如果一个点在仍被占用时查询器状态,就会把它需要等待的时间恢复到600s,但这个点不一定是heap2堆顶,我们也就无法取出它并且进行修改。
但是不需要取出啊,我们可以再用一个数组change[i]表示一个点在被占用的时候被查询的时间点,每次在取出heap2堆顶的过程中,对每一个取出的点判断其change数组是否合法,若不合法,则令其time=change,完成更新,插回heap2中。
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e4+40;
int len1,len2,heap1[maxn];
int change[maxn];
bool vis[maxn];
struct mint
{
int id,time;
}heap2[maxn];
void insert1(int k)
{
heap1[++len1]=k;
int pla=len1;
while(pla>1)
{
int fa=pla/2;
if(heap1[fa]<heap1[pla]) break;
swap(heap1[fa],heap1[pla]);
pla=fa;
}
}
int get1()
{
int res=heap1[1];
heap1[1]=heap1[len1--];
int pla=1;
while(pla*2<=len1)
{
int son=pla*2;
if(son+1<=len1&&heap1[son]>heap1[son+1]) son++;
if(heap1[pla]<heap1[son]) break;
swap(heap1[son],heap1[pla]);
pla=son;
}
return res;
}
void insert2(mint k)
{
heap2[++len2]=k;
int pla=len2;
while(pla>1)
{
int fa=pla/2;
if(heap2[fa].time<heap2[pla].time) break;
swap(heap2[fa],heap2[pla]);
pla=fa;
}
}
mint get2()
{
mint res=heap2[1];
heap2[1]=heap2[len2--];
int pla=1;
while(pla*2<=len2)
{
int son=pla*2;
if(son+1<=len2 && heap2[son].time>heap2[son+1].time) son++;
if(heap2[pla].time < heap2[son].time) break;
swap(heap2[pla],heap2[son]);
pla=son;
}
return res;
}
int main()
{
int n,q;
char a;
for(int i=1;i<=30000;++i) insert1(i);
while(scanf("%d",&n)!=EOF)
{
while(1)
{
if(len2==0) break;
mint g=get2();
if(g.time+600>n)
{
insert2(g);
break;
}
if(change[g.id]+600>n)
{
g.time=change[g.id];
insert2(g);
}
else
{
vis[g.id]=false;
insert1(g.id);
}
}
cin>>a;
// printf("%c\n",a);
if(a!='.')
{
int k=get1();
vis[k]=true;
mint g;
g.id=k;
g.time=n;
insert2(g);
printf("%d\n",g.id);
}
else
{
scanf("%d",&q);
if(vis[q])
{
printf("+\n");
change[q]=n;
}
else printf("-\n");
}
}
return 0;
}
总结:
根据这个题的分析过程,以及对无法取出的点的更新方式,我们可以得出一些比较普遍性的思路:
(1)多个堆维护多种数据,完成复杂的修改过程。
(2)设置一个额外的数组,来完成对当前无法取出的点的更新,并在它被取出时用这个数组对其判断是否合法,或者更新。
原文地址:https://www.cnblogs.com/mint-hexagram/p/15263239.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- [Java] Java多线程的探索 -获取新闻标题
- Java中对文件进行MD5加密
- [数据结构] 使用最小堆思想实现哈夫曼编解码
- [数据结构] 括号符的匹配
- [数据结构] 平衡二叉查找树 (AVL树)
- 写给前端的算法进阶指南,我是如何两个月零基础刷200题
- [Java] 在Java中优雅地进行文件IO操作
- [Java] 日期与时间的一些操作
- 一起来用python实现一下十大经典排序算法
- [数据结构] 稀疏矩阵的存储
- [Python] 关于 asyncio 与 aiohttp 协程并发的探索
- [数据结构]结构体练习之复数运算
- [数据结构] 队列的链式存储实现
- [数据结构] 两个有序线性表的合并
- Spring 简介,带你打开 Spring 的大门