您的位置:首页 > 其它

hdoj 2871 Memory Control 【线段树lazy + 区间合并 + 二维vector的查询、插入、删除】

2015-09-17 19:58 417 查看

Memory Control

Time 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




题意:有n个单元的内存(连续的)和m个操作。我们称 每次开辟的连续单元的内存为block。

操作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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: