题意:
模拟一个内存分配机制。
Reset:重置,释放所有空间
New x:申请内存为x的空间,输出左地址
Free x:释放地址x所在的内存块
Get x:查询第x个内存块,输出左地址
解析:
可以用一个vector来记录所有的内存块的区间。
New x操作可以利用如同POJ3667中的query操作查找到最右边的位置。然后把找到的区间二分插入,vector中。
Free x操作,由于每个内存块的区间都是互不相交的,所以可以二分找到离x最近的开始位置,释放该内存块。
Get x操作就直接输出第x个内存块的开始地址。
Reset操作可以直接利用modify更新,而不要重新build,这样会更快。
my code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
#define LEN(L, R) ((R) - (L) + 1)
#define MID (L + R) >> 1
#define pb push_back
using namespace std;
const int N = 50010;
struct Segment { int st, en; };
int n, m;
vector<Segment> list;
int mxL[N<<2], mxR[N<<2], mx[N<<2];
int cov[N<<2];
int max(int a, int b, int c) {
return max(a, max(b, c));
}
inline void maintain (int o, int L, int R, int val) {
cov[o] = val;
mxL[o] = mxR[o] = mx[o] = (val ? 0 : LEN(L, R));
}
inline void pushUp (int o, int L, int R) {
int M = MID;
mx[o] = max(mx[ls], mx[rs], mxL[rs] + mxR[ls]);
mxL[o] = mxL[ls] + (mxL[ls] == LEN(L, M) ? mxL[rs] : 0);
mxR[o] = mxR[rs] + (mxR[rs] == LEN(M+1, R) ? mxR[ls] : 0);
}
inline void pushDown (int o, int L, int R) {
if (cov[o] != -1) {
int M = MID;
maintain(lson, cov[o]);
maintain(rson, cov[o]);
cov[o] = -1;
}
}
void build (int o, int L, int R) {
cov[o] = -1;
if (L == R) {
maintain(o, L, R, 0);
return;
}
int M = MID;
build(lson);
build(rson);
pushUp(o, L, R);
}
void modify(int o, int L, int R, int ql, int qr, int val) {
if(ql <= L && R <= qr) {
maintain(o, L, R, val);
return ;
}
int M = MID;
pushDown(o, L, R);
if(ql <= M) modify(lson, ql, qr, val);
if(qr > M) modify(rson, ql, qr, val);
pushUp(o, L, R);
}
int query(int o, int L, int R, int need) {
if(L == R) return L;
int M = MID, ret = 0;
pushDown(o, L, R);
if(mx[ls] >= need) ret = query(lson, need);
else if(mxR[ls] + mxL[rs] >= need)
ret = M - mxR[ls] + 1;
else ret = query(rson, need);
pushUp(o, L, R);
return ret;
}
int search(int x) {
int L = 0, R = list.size()-1;
while(L <= R) {
int M = MID;
int tmp = list[M].st;
if(tmp <= x) L = M + 1;
else R = M - 1;
}
return L;
}
void New(int x) {
if(mx[1] < x) puts("Reject New");
else {
int ql = query(1, 1, n, x);
int qr = ql + x - 1;
int pos = search(ql);
list.insert(list.begin()+pos, (Segment){ql, qr});
modify(1, 1, n, ql, qr, 1);
printf("New at %d\n", ql);
}
}
void Free(int x) {
int pos = search(x) - 1;
if(pos < 0 || list[pos].en < x) {
puts("Reject Free");
}else {
int ql = list[pos].st, qr = list[pos].en;
printf("Free from %d to %d\n", ql, qr);
modify(1, 1, n, ql, qr, 0);
list.erase(list.begin() + pos, list.begin() + pos + 1);
}
}
void Get(int x) {
if(x > list.size()) {
puts("Reject Get");
}else {
printf("Get at %d\n", list[x-1].st);
}
}
int main () {
char op[5];
int x;
while (scanf("%d%d", &n, &m) == 2) {
build (1, 1, n);
list.clear();
char op[5];
while (m--) {
scanf("%s", op);
if(op[0] == 'N') {
scanf("%d", &x);
New(x);
}else if(op[0] == 'F') {
scanf("%d", &x);
Free(x);
}else if(op[0] == 'G') {
scanf("%d", &x);
Get(x);
}else if(op[0] == 'R') {
modify(1, 1, n, 1, n, 0);
list.clear();
puts("Reset Now");
}
}
printf("\n");
}
return 0;
}