HDU-2871 Memory Control 线段树-区间合并

题目大意为给定一段内存快,要求根据命令输出正确的答案。

New x    申请长度为x的空白内存的首地址,如果不满足输出Reject New
Free x    释放包含x节点的内存块,注意该内存块为一个New操作所确定的区域,即不必要将物理相邻的内存块视作一个内存块
Get x     得到从左到右的第x个内存块 
Reset     重置总区间

针对这些要求,设定一棵线段树,每个节点保留左,右连续空白段,以及区间总长。这样便能够处理New命令,而Free以及Get命令则用vector保留,用二分搜索优化。

代码如下:

View Code
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#define MAXN 50000
using namespace std;

struct
{
int l, r;
int lmax, rmax, max, cover;
}seg[MAXN*4];

struct Node
{
int s, e;
}info;

void up(int f)
{
seg[f].lmax = seg[f<<1].lmax;
seg[f].rmax = seg[f<<1|1].rmax;
if (seg[f<<1].cover == 0)
seg[f].lmax += seg[f<<1|1].lmax;
if (seg[f<<1|1].cover == 0)
seg[f].rmax += seg[f<<1].rmax;
seg[f].max = max(seg[f<<1].max, seg[f<<1|1].max);
seg[f].max = max(seg[f].max, seg[f<<1].rmax+seg[f<<1|1].lmax);
if (seg[f<<1].cover == seg[f<<1|1].cover)
seg[f].cover = seg[f<<1].cover;
else
seg[f].cover = -1;
}

void build(int f, int l, int r)
{
int mid = l+r >> 1;
seg[f].l = l, seg[f].r = r;
seg[f].lmax = seg[f].rmax = seg[f].max = r-l+1;
seg[f].cover = 0;
if (r > l)
{
build(f<<1, l, mid);
build(f<<1|1, mid+1, r);
}
}

void modify(int f, int l, int r, int val)
{
int mid = seg[f].l+seg[f].r >> 1;
if (seg[f].l == l && r == seg[f].r)
{
seg[f].cover = val;
if (val == 1) // 如果是占用命令
seg[f].lmax = seg[f].rmax = seg[f].max = 0;
else
seg[f].lmax = seg[f].rmax = seg[f].max = r-l+1;
}
else if (seg[f].r > seg[f].l)
{
if (seg[f].cover == 0)
{ // lazy 操作 相当于格式化一般的向下更新
seg[f<<1].cover = seg[f<<1|1].cover = 0;
seg[f<<1].lmax = seg[f<<1].r-seg[f<<1].l+1;
seg[f<<1].rmax = seg[f<<1].r-seg[f<<1].l+1;
seg[f<<1].max = seg[f<<1].r-seg[f<<1].l+1;
seg[f<<1|1].lmax = seg[f<<1|1].r-seg[f<<1|1].l+1;
seg[f<<1|1].rmax = seg[f<<1|1].r-seg[f<<1|1].l+1;
seg[f<<1|1].max = seg[f<<1|1].r-seg[f<<1|1].l+1;
seg[f].cover = -1;
}
else if (seg[f].cover == 1)
{
seg[f<<1].cover = seg[f<<1|1].cover = 1;
seg[f<<1].lmax = 0;
seg[f<<1].rmax = 0;
seg[f<<1].max = 0;
seg[f<<1|1].lmax = 0;
seg[f<<1|1].rmax = 0;
seg[f<<1|1].max = 0;
seg[f].cover = -1;
}
if (r <= mid)
modify(f<<1, l, r, val);
else if (l > mid)
modify(f<<1|1, l, r, val);
else
{
modify(f<<1, l, mid, val);
modify(f<<1|1, mid+1, r, val);
}
up(f);
}
}

int query(int f, int size)
{
int mid = seg[f].l+seg[f].r >> 1;
if (seg[f].max < size)
return 0;
else if (seg[f].r > seg[f].l)
{
if (seg[f].lmax >= size)
{
return seg[f].l;
}
else if (seg[f<<1].max >= size)
return query(f<<1, size);
else if (seg[f<<1].rmax+seg[f<<1|1].lmax >= size)
return seg[f<<1].r-seg[f<<1].rmax+1;
else
return query(f<<1|1, size);
}
}

int bsearch(int pos, vector<Node>&v, int way)
{
int l = 0, r = v.size()-1;
while (l <= r)
{
int mid = l+r >> 1;
if (pos > v[mid].s)
l = mid + 1;
else if (pos < v[mid].s)
r = mid - 1;
else if (way == 1)
return mid;
}
if (way == 0)
return l;
else
return r;
}

int main()
{
int N, M, x, loc;
char op[10];
while (scanf("%d %d", &N, &M) == 2)
{
build(1, 1, N);
vector<Node>v;
vector<Node>::iterator it;
while (M--)
{
scanf("%s", op);
if (op[0] == 'R')
{
seg[1].lmax = seg[1].rmax = seg[1].max = N;
seg[1].cover = 0;
v.clear();
puts("Reset Now");
}
else if (op[0] == 'N')
{
scanf("%d", &x);
int pos = query(1, x);
if (pos == 0)
puts("Reject New");
else
{
printf("New at %d\n", pos);
modify(1, pos, pos+x-1, 1);
it = v.begin()+bsearch(pos, v, 0);
info.s = pos, info.e = pos+x-1;
v.insert(it, info);
}
}
else if (op[0] == 'F')
{
scanf("%d", &x);
loc = bsearch(x, v, 1);
if (loc == -1)
puts("Reject Free");
else
{
it = v.begin()+loc;
if (x >= it->s && x <= it->e)
{
printf("Free from %d to %d\n", it->s, it->e);
modify(1, it->s, it->e, 0);
v.erase(it);
}
else
puts("Reject Free");
}
}
else
{
scanf("%d", &x);
if (x > v.size())
puts("Reject Get");
else
printf("Get at %d\n", v[x-1].s);
}
}
puts("");
}
return 0;
}



posted @ 2012-03-07 20:39  沐阳  阅读(461)  评论(0编辑  收藏  举报