HDU 2871 Memory Control(线段树区间合并+二分)

来源:互联网 发布:软件资格考试成绩查询 编辑:程序博客网 时间:2024/05/06 05:25

题意:

模拟一个内存分配机制。
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_backusing 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;}
0 0
原创粉丝点击