热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HDU2871内存管理问题(线段树优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871。本题涉及内存管理操作,包括重置、申请、释放和查询内存块。通过使用线段树进行高效管理和维护。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871


题意描述:给定一段内存空间,支持以下四种操作:



  • Reset:重置所有内存。

  • New x:申请一块大小为x的内存,返回最左边可用的起始地址。

  • Free x:释放包含地址x的内存块。

  • Get x:获取第x块内存的首地址。


解题思路:此题需要处理复杂的内存分配与释放操作,线段树是一种有效的数据结构选择。为了方便处理free和get操作,可以结合Vector来辅助实现。线段树主要负责维护内存的连续长度和最大连续长度。


具体实现中,ll[rt]表示该区段从左开始的连续内存长度,rr[rt]表示从右开始的连续内存长度,mlen[rt]表示该区间内的最大连续内存长度。这样的维护方式能够确保在线段树中任意操作区间的高效性。



#include 
#include
#include
using namespace std;

#define F(i, a, b) for(int i = (a); i <= (b); ++i)
#define root 1, n, 1
#define ls l, m, rt <<1
#define rs m + 1, r, rt <<1 | 1
#define Max(a, b) ((a) > (b) ? (a) : (b))

struct edge {
int l, r;
bool operator<(const edge& b) const { return l };

const int maxn = 50010;
int n, m, num, ll[maxn <<2], rr[maxn <<2], lazy[maxn <<2], mlen[maxn <<2];
vector Q;

inline void pup(int l, int r, int rt) {
int m = (l + r) >> 1;
mlen[rt] = Max(mlen[rt <<1], mlen[rt <<1 | 1]);
mlen[rt] = Max(mlen[rt], rr[rt <<1] + ll[rt <<1 | 1]);
ll[rt] = ll[rt <<1] + (ll[rt <<1] == m - l + 1 ? ll[rt <<1 | 1] : 0);
rr[rt] = rr[rt <<1 | 1] + (rr[rt <<1 | 1] == r - m ? rr[rt <<1] : 0);
}

inline void pdown(int l, int r, int rt) {
if (lazy[rt] != -1) {
lazy[rt <<1] = lazy[rt <<1 | 1] = lazy[rt];
int m = (l + r) >> 1;
mlen[rt <<1] = ll[rt <<1] = rr[rt <<1] = (lazy[rt] == 0 ? m - l + 1 : 0);
mlen[rt <<1 | 1] = rr[rt <<1 | 1] = ll[rt <<1 | 1] = (lazy[rt] == 0 ? r - m : 0);
lazy[rt] = -1;
}
}

int New(int l, int r, int rt, int num) {
if (l == r) return l;
int m = (l + r) >> 1;
pdown(l, r, rt);
if (mlen[rt <<1] >= num) return New(ls, num);
else if (rr[rt <<1] + ll[rt <<1 | 1] >= num) return m - rr[rt <<1] + 1;
else return New(rs, num);
}

void covr(int op, int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
lazy[rt] = op;
ll[rt] = rr[rt] = mlen[rt] = (op == 0 ? r - l + 1 : 0);
return;
}
pdown(l, r, rt);
int m = (l + r) >> 1;
if (L <= m) covr(op, L, R, ls);
if (R > m) covr(op, L, R, rs);
pup(l, r, rt);
}

void reset() {
Q.clear();
Q.push_back(edge{0, 0});
Q.push_back(edge{100000, 100000});
covr(0, 1, n, root);
}

void insert(edge xx) {
int now = upper_bound(Q.begin(), Q.end(), xx) - Q.begin();
Q.insert(Q.begin() + now, xx);
}

int main() {
char op[20];
edge s = {0, 0}, e = {100000, 100000};
while (~scanf("%d%d", &n, &m)) {
reset();
while (m--) {
scanf("%s", op);
if (op[0] != 'R') scanf("%d", &num);
if (op[0] == 'N') {
if (mlen[1] else {
int x = New(root, num);
printf("New at %d\n", x);
edge tp = {x, x + num - 1};
covr(1, tp.l, tp.r, root);
insert(tp);
}
} else if (op[0] == 'F') {
edge tp = {num, num};
int now = upper_bound(Q.begin(), Q.end(), tp) - Q.begin() - 1;
if (Q[now].l <= num && Q[now].r >= num) {
covr(0, Q[now].l, Q[now].r, root);
printf("Free from %d to %d\n", Q[now].l, Q[now].r);
Q.erase(Q.begin() + now);
} else puts("Reject Free");
} else if (op[0] == 'G') {
if (num > Q.size() - 2) puts("Reject Get");
else printf("Get at %d\n", Q[num].l);
} else {
reset();
puts("Reset Now");
}
}
puts("");
}
return 0;
}


推荐阅读
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ... [详细]
  • 本实验主要探讨了二叉排序树(BST)的基本操作,包括创建、查找和删除节点。通过具体实例和代码实现,详细介绍了如何使用递归和非递归方法进行关键字查找,并展示了删除特定节点后的树结构变化。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • Splay Tree 区间操作优化
    本文详细介绍了使用Splay Tree进行区间操作的实现方法,包括插入、删除、修改、翻转和求和等操作。通过这些操作,可以高效地处理动态序列问题,并且代码实现具有一定的挑战性,有助于编程能力的提升。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • 本文深入探讨了C++对象模型中的一些细节问题,特别是虚拟继承和析构函数的处理。通过具体代码示例和详细分析,揭示了书中某些观点的不足之处,并提供了更合理的解释。 ... [详细]
  • 本文详细介绍了VMware的多种认证选项,帮助你根据职业需求和个人技能选择最合适的认证路径,涵盖从基础到高级的不同层次认证。 ... [详细]
author-avatar
手机用户2502853447_666
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有