hdoj 2871 Memory Control 【线段树lazy + 区间合并 + 二维vector的查询、插入、删除】
2015-09-17 19:58
417 查看
Memory ControlTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5591 Accepted Submission(s): 1299 Problem Description Memory units are numbered from 1 up to N. A sequence of memory units is called a memory block. The memory control system we consider now has four kinds of operations: 1. Reset Reset all memory units free. 2. New x Allocate a memory block consisted of x continuous free memory units with the least start number 3. Free x Release the memory block which includes unit x 4. Get x Return the start number of the xth memory block(Note that we count the memory blocks allocated from left to right) Where 1<=x<=N.You are request to find out the output for M operations. Input Input contains multiple cases. Each test case starts with two integer N,M(1<=N,M<=50000) ,indicating that there are N units of memory and M operations. Follow by M lines,each line contains one operation as describe above. Output For each “Reset” operation, output “Reset Now”. For each “New” operation, if it’s possible to allocate a memory block, output “New at A”,where Ais the least start number,otherwise output “Reject New”. For each “Free” operation, if it’s possible to find a memory block occupy unit x, output “Free from A to B”,where A and B refer to the start and end number of the memory block,otherwise output “Reject Free”. For each “Get” operation, if it’s possible to find the xth memory blocks, output “Get at A”,where A is its start number,otherwise output “Reject Get”. Output one blank line after each test case. Sample Input 6 10 New 2 New 5 New 2 New 2 Free 3 Get 1 Get 2 Get 3 Free 3 Reset Sample Output New at 1 Reject New New at 3 New at 5 Free from 3 to 4 Get at 1 Get at 5 Reject Get Reject Free Reset Now |
操作1 —— New x
表示开辟一个新的block,使它具有连续x单元的内存且要求起点最小。若无法开辟新block输出Reject New,否则输出新block的起点。
操作2 —— Free x
表示释放x单元所在的block。若找不到该block输出Reject Free,否则输出该block的起点和终点。
操作3 —— Get x
表示找到第x个block(从左向右数),若不能找到输出Reject Get,否则输出该block的起点。
操作4 —— Reset
表示清空所有内存。
使用好vector——是做这道题的关键。
至于线段树就是区间合并,重在PushUp函数的操作。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define MAXN 50000+10 #define lson o<<1, l, mid #define rson o<<1|1, mid+1, r #define ll o<<1 #define rr o<<1|1 using namespace std; struct Tree { int l, r, len; int lsum, rsum; int sum; int lazy; }; Tree tree[MAXN<<2]; void PushUp(int o) { tree[o].lsum = tree[ll].lsum; tree[o].rsum = tree[rr].rsum; if(tree[ll].lsum == tree[ll].len)//左半区间 可以全部容纳 tree[o].lsum += tree[rr].lsum; if(tree[rr].rsum == tree[rr].len) tree[o].rsum += tree[ll].rsum; //更新最值 (左子树最值, 右子树最值, 左子树右连续长度 + 右子树左连续长度) tree[o].sum = max(max(tree[ll].sum, tree[rr].sum), tree[ll].rsum + tree[rr].lsum); } void build(int o, int l, int r) { tree[o].l = l; tree[o].r = r; tree[o].len = tree[o].lsum = tree[o].rsum = tree[o].sum = r - l + 1; tree[o].lazy = -1; if(l == r) return ; int mid = (l + r) >> 1; build(lson); build(rson); } void PushDown(int o) { if(tree[o].lazy != -1) { tree[ll].lazy = tree[rr].lazy = tree[o].lazy; tree[ll].lsum = tree[ll].rsum = tree[ll].sum = tree[o].lazy ? 0 : tree[ll].len; tree[rr].lsum = tree[rr].rsum = tree[rr].sum = tree[o].lazy ? 0 : tree[rr].len; tree[o].lazy = -1; } } int query(int need, int o) { if(tree[o].l == tree[o].r) return tree[o].l; PushDown(o);//下传 lazy标记 int mid = (tree[o].l + tree[o].r) >> 1; //查询顺序 不能变 if(need <= tree[ll].sum) return query(need, ll); else if(need <= tree[ll].rsum + tree[rr].lsum) return mid - tree[ll].rsum + 1; else if(need <= tree[rr].sum) return query(need, rr); } void update(int L, int R, int o, int v) { if(L <= tree[o].l && R >= tree[o].r) { tree[o].lsum = tree[o].rsum = tree[o].sum = v ? 0 : tree[o].len; tree[o].lazy = v; return ; } PushDown(o); int mid = (tree[o].l + tree[o].r) >> 1; if(R <= mid) update(L, R, ll, v); else if(L > mid) update(L, R, rr, v); else { update(L, mid, ll, v); update(mid+1, R, rr, v); } PushUp(o);//维护 上区间 } struct Node { int s, e;//block 起点 终点 }; vector<Node> G; vector<Node> ::iterator it; bool cmp(Node a, Node b) { return a.s < b.s;//起点升序排列 } int main() { int n, m; while(scanf("%d%d", &n, &m) != EOF) { G.clear();//初始化 build(1, 1, n);//建树 while(m--) { char op[10]; int x, pos; scanf("%s", op); if(op[0] == 'N') { scanf("%d", &x); if(tree[1].sum < x)//不能容纳内存 printf("Reject New\n"); else { pos = query(x, 1);//查询最小起点 printf("New at %d\n", pos); update(pos, pos+x-1, 1, 1);//占据 连续的空间 Node E = {pos, pos+x-1};//容器存储 it = upper_bound(G.begin(), G.end(), E, cmp);//查询起点大于E.s的第一个 block G.insert(it, E);//插入 } } else if(op[0] == 'F') { scanf("%d", &x);//去掉x所在的 block Node E = {x, x}; it = upper_bound(G.begin(), G.end(), E, cmp);//查询起点大于E.s的第一个 block pos = it - G.begin() - 1;//得到需要的block在vector里面的下标 //判断是否在 该block里面 if(pos < 0 || G[pos].s > x || G[pos].e < x) printf("Reject Free\n"); else { update(G[pos].s, G[pos].e, 1, 0); printf("Free from %d to %d\n", G[pos].s, G[pos].e); G.erase(G.begin() + pos); } } else if(op[0] == 'G') { scanf("%d", &x);//第x个block x -= 1; if(x < 0 || x >= G.size()) printf("Reject Get\n"); else printf("Get at %d\n", G[x].s); } else { printf("Reset Now\n"); G.clear(); update(1, n, 1, 0);//释放所有内存 } } printf("\n"); } return 0; }
相关文章推荐
- Android四大基本组件介绍与生命周期
- Objective-C 【copy的概念-深拷贝-浅拷贝】
- 开源中国 Maven 库使用帮助
- log4j是什么,log4j解决了什么问题,log4j怎么用
- IOS:知乎上的一个怎么面试iOS工程师的问题
- python的内存管理
- Oracle11g opatch打补丁
- java笔记——面向对象异常
- android学习:service的创建,打开、关闭一个service
- 怎么让input不失去焦点
- Android 加密解密Base64
- Request的getParameter和getAttribute方法的区别
- android绘图Path类仿加速球水面波动效果
- 系统表 sys.syscolumns、sys.sysobjects 和 sys.indexes 的字段含义
- SVN版本控制器中各符号的含义
- something about consistency form my perspective
- SVN版本控制器中各符号的含义
- iOS-文件断点续传
- Linux常用命令
- $_FILES 数组为空