HDU 2871 Memory Control (线段树,区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=2871

Memory Control

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4418    Accepted Submission(s): 1056

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

Source

2009 Multi-University Training
Contest 7 - Host by FZU

题意:

Reset:清空内存

New x:申请长度为x的内存

Free x:释放x所在的内存块

Get x:询问x所在内存块的起点

分析:

New操作用线段树,找到能容纳x的最左的位置,维护节点的左/右起最长连续0的长度和对应区间内最长连续0的长度。

把现有内存块保存,用二分查找/更新即可,注意Reset时要清空。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cctype>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm
#define maxn 200007

using namespace std;

int setv[maxn<<2];
int lsum0[maxn<<2],rsum0[maxn<<2],msum0[maxn<<2];

struct Memory
{
    int l,r;
};

vector<Memory> v;

inline void pushup(int k,int l,int r)
{
    int lc=k*2+1,rc=k*2+2,m=l+r>>1;

    if (lsum0[lc]==m-l)   lsum0[k]=lsum0[lc]+lsum0[rc]; else    lsum0[k]=lsum0[lc];
    if (rsum0[rc]==r-m)   rsum0[k]=rsum0[rc]+rsum0[lc]; else    rsum0[k]=rsum0[rc];
    msum0[k]=max(rsum0[lc]+lsum0[rc],max(msum0[lc],msum0[rc]));

}

inline void pushdown(int k,int l,int r)
{
    if (setv[k]!=-1)
    {
        int lc=k*2+1,rc=k*2+2,m=l+r>>1;
        setv[lc]=setv[rc]=setv[k];

        lsum0[lc]=rsum0[lc]=msum0[lc]=setv[k]?0:m-l;

        lsum0[rc]=rsum0[rc]=msum0[rc]=setv[k]?0:r-m;

        setv[k]=-1;
    }
}

void update(int a,int b,int v,int k,int l,int r)
{
    if (b<=l || r<=a)   return ;
    if (a<=l && r<=b)
    {
        setv[k]=v;
        lsum0[k]=rsum0[k]=msum0[k]=v?0:r-l;
    }
    else
    {
        pushdown(k,l,r);
        update(a,b,v,k*2+1,l,l+r>>1);
        update(a,b,v,k*2+2,l+r>>1,r);
        pushup(k,l,r);
    }
}

int query(int w,int k,int l,int r)
{
    int lc=k*2+1,rc=k*2+2,m=l+r>>1;

    if (r-l==1) return l;

    if (r-l!=1) pushdown(k,l,r);

    if (msum0[lc]>=w) return query(w,lc,l,m);
    if (rsum0[lc]+lsum0[rc]>=w)     return m-rsum0[lc];
    return query(w,rc,m,r);
}

int bin_search(int k)
{
    int l=0,r=v.size()-1,ans=-1;

    while (l<=r)
    {
        itn mid=l+r>>1;
        if (v[mid].l<=k)
        {
            l=mid+1;
            ans=mid;
        }
        else
        {
            r=mid-1;
        }
    }

    return ans;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("/home/fcbruce/文档/code/t","r",stdin);
    #endif // ONLINE_JUDGE

    int n,m,w,a,b,p;
    char op[10];

    while (~scanf("%d %d",&n,&m))
    {
        v.clear();
        update(0,n,0,0,0,n);

        while (m--)
        {
            scanf("%s",op);
            if (op[0]=='R')
            {
                v.clear();
                puts("Reset Now");
                update(0,n,0,0,0,n);
                continue;
            }

            if (op[0]=='N')
            {
                scanf("%d",&w);
                if (w<=msum0[0])
                {
                    a=query(w,0,0,n);
                    b=a+w;
                    update(a,b,1,0,0,n);
                    printf("New at %d\n",a+1);
                    Memory temp;
                    temp.l=a+1;
                    temp.r=b;
                    int id=bin_search(a+1)+1;
                    v.insert(v.begin()+id,temp);

                }
                else
                    puts("Reject New");
                continue;
            }

            if (op[0]=='F')
            {
                scanf("%d",&p);

                int id=bin_search(p);

                if (id==-1 || v[id].r<p)
                    puts("Reject Free");
                else
                {
                    printf("Free from %d to %d\n",v[id].l,v[id].r);
                    update(v[id].l-1,v[id].r,0,0,0,n);
                    v.erase(v.begin()+id,v.begin()+id+1);
                }
                continue;
            }

            if (op[0]=='G')
            {
                scanf("%d",&w);
                if (w<=v.size())
                    printf("Get at %d\n",v[w-1].l);
                else
                    puts("Reject Get");
            }
        }

        puts("");
    }

    return 0;
}
时间: 2024-08-23 15:49:43

HDU 2871 Memory Control (线段树,区间合并)的相关文章

hdu 2871 Memory Control(线段树)

题目链接:hdu 2871 Memory Control 题目大意:模拟一个内存分配机制. Reset:重置,释放所有空间 New x:申请内存为x的空间,输出左地址 Free x:释放地址x所在的内存块 Get x:查询第x个内存块,输出左地址 解题思路:一开始全用线段树去做,写的乱七八糟,其实只要用线段树维护可用内存.然后用户一个vector记录所有的内存块. #include <cstdio> #include <cstring> #include <vector>

HDU 5316 Magician(线段树区间合并入门)

本文纯属原创,转载请注明出处谢谢.http://blog.csdn.net/zip_fan. 题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5316 Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Fantasy magicians usually gain their ability

HDU 5316——Magician——————【线段树区间合并区间最值】

Magician Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1613    Accepted Submission(s): 470 Problem Description Fantasy magicians usually gain their ability through one of three usual methods:

HDU - 3308 - LCIS (线段树 - 区间合并)

题目传送:LCIS 线段树,区间合并,一次过啦,没有纠结,这几天过的最愉快的一个题 思路:求最长连续上升子序列,外带单点更新,经典的线段树题目.具体看代码注释 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack>

hdu 4453 约会安排(线段树区间合并)

约会安排 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 433    Accepted Submission(s): 145 Problem Description 寒假来了,又到了小明和女神们约会的季节. 小明虽为屌丝级码农,但非常活跃,女神们常常在小明网上的大段发言后热情回复“呵呵”,所以,小明的最爱就是和女神们约会.与此同时,也有

HDU 1540 POJ 2892 线段树区间合并

给出N个点,M次操作,N个点开始在一条线上链式相连 D操作  把某点删除掉 Q操作  询问某点一共可以连接多少个点 R操作  把上一次删除的点还原 线段树处理区间合并 分别记录每个区间的左端连续最长和右端连续最长 #include "stdio.h" #include "string.h" struct node { int l,r,lx,rx,x; }data[200010]; int mark[50100]; int Max(int a,int b) { if

HDU 1540 Tunnel Warfare(线段树 区间合并 最大连续区间)

题意  有n个连在一起的地道  接下来有m个操作  D x 炸掉x号地道  炸掉后x所在的区间就不连续了  Q x 查询输出包括x的最大连续区间长度   R修复最后一个被炸的地道  注意输入R时可能并没有需要修复的地道 线段树的区间合并问题  线段树要维护3个信息 len  对应区间的最大连续长度 ll  对应区间最左端的一段连续长度 lr  对应区间最右端的一段连续长度 那么双亲节点的这些信息和孩子节点有什么关系呢  容易发现 双亲的len 是 左孩子的len 右孩子的len  左孩子的右端长

hdu 3397 Sequence operation (线段树 区间合并 多重标记)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问区间1的个数 4.询问区间被最长连续1的长度 思路: 这5个操作都是比较基础的线段树操作,难点在于有两种修改操作,这类题之前也写过,之前是乘法和加法,这个是区间亦或和区间更新值,但是思路是可以借鉴的,我们要推出这两个操作的关系,这样才能维护好这两个标记,我们用两个标记:same , rev ,分别表

(简单) HDU 3308 LCIS,线段树+区间合并。

Problem Description Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting from 0) Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b]. 题目大意就是给你一个数列,求区间内的最长连续子序列.以及对某一个点的