hdu2871(线段树区间合并+vector+二分)

题目链接:hdu2871

/*hdu 2871 区间合并,成段更新,vector
poj 3667 升级版
题意:现在有1到N(N <= 50000)个连续内存单元,连续的n块内存单元能
组成一个内存块,然后给出四种操作:
    1. Reset 释放所有内存块,并且输出“Reset Now”。
    2. New x 申请一块有连续x个内存单元的空间,如果有多个,选择最左端的,
然后输出“New at A", A表示最左端的那个内存单元;否则输出“Reject New”。
    3. Free x 释放包含第x个内存单元的那个内存块,并且输出“Free from A to B”,
A到B表示内存块的左右端点;否则输出“Reject Free”。
    4. Get x 找到第x个内存块,如果找到,输出“Get at A”,
A表示第x块内存块的最左端的内存单元编号,否则输出“Reject Get”。
注意:内存块的编号从左到右依次增大

思路:
    用一个vector来保存申请的内存块的左右端点,在vector中的位置就
表示内存块的编号,当申请一个内存块时,二分查找这个内存块在vector中的
位置,然后插入
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
const int N = 500010;
struct node
{
    int l,r,c;
    int lsum,rsum,sum;
}s[N<<2];
struct block
{
    int l,r;
    bool operator < (const block &cmp) const{
        return l < cmp.l;
    }
};
void pushdown(int rt, int m)
{
    if(s[rt].c != -1){
        s[lson].lsum = s[lson].rsum = s[lson].sum = s[rt].c?0:m-(m>>1);
        s[rson].lsum = s[rson].rsum = s[rson].sum = s[rt].c?0:m>>1;
        s[lson].c = s[rson].c = s[rt].c;
        s[rt].c = -1;
    }
}
void pushup(int rt, int m)
{
    s[rt].lsum = s[lson].lsum;
    s[rt].rsum = s[rson].rsum;
    s[rt].sum = max(s[lson].sum, s[rson].sum);
    if(s[lson].lsum == m-(m>>1))
        s[rt].lsum += s[rson].lsum;
    if(s[rson].rsum == m>>1)
        s[rt].rsum += s[lson].rsum;
    s[rt].sum = max(s[rt].sum, s[lson].rsum + s[rson].lsum);
}
void build(int l, int r, int rt)
{
    s[rt].l = l;  s[rt].r = r;
    s[rt].lsum = s[rt].rsum = s[rt].sum = r-l+1;
    s[rt].c = -1;
    if(l == r) return;
    int mid = (l+r) >> 1;
    build(l, mid, lson);
    build(mid+1, r, rson);
}
void updata(int c, int l, int r, int rt)
{
    if(l <= s[rt].l && s[rt].r <= r){
        s[rt].c = c;
        s[rt].lsum = s[rt].rsum = s[rt].sum = c?0:s[rt].r-s[rt].l+1;
        return;
    }
    pushdown(rt, s[rt].r-s[rt].l+1);
    int mid = (s[rt].l+s[rt].r)>>1;
    if(l <= mid)
        updata(c, l, r, lson);
    if(mid < r)
        updata(c, l, r, rson);
    pushup(rt, s[rt].r-s[rt].l+1);
}
int query(int num, int rt)
{
    if(s[rt].l == s[rt].r) return s[rt].l;
    int mid = (s[rt].l + s[rt].r) >> 1;
    pushdown(rt, s[rt].r-s[rt].l+1);
    if(s[lson].sum >= num)
        return query(num, lson);
    if(s[lson].rsum + s[rson].lsum >= num)
        return mid-s[lson].rsum + 1;
    //if(s[rson].sum >= num)
        return query(num, rson);
}
vector <block> v;
int main()
{
    int n,m,x;
    char a[10];
    while(~scanf("%d%d",&n,&m))
    {
        build(1, n, 1);
        v.clear();
        while(m--){
            scanf("%s",a);
            if(a[0] == 'N'){//申请内存块
                scanf("%d",&x);
                if(s[1].sum < x) puts("Reject New");
                else{
                    int pos = query(x, 1);//找到最左端的那个内存单元的编号
                    printf("New at %d\n",pos);
                    updata(1, pos, pos+x-1, 1);//更新
                    block tmp;
                    tmp.l = pos;  tmp.r = pos+x-1;
                    vector<block>::iterator iter;//索引
                    iter = upper_bound(v.begin(), v.end(), tmp);//二分查找
                    v.insert(iter, tmp);
                }
            }
            if(a[0] == 'F'){//释放内存块
                scanf("%d",&x);
                block tmp;
                tmp.l = tmp.r = x;//假设第x个内存单元是一个内存块
                vector<block>::iterator iter;
                iter = upper_bound(v.begin(), v.end(), tmp);
                int pos = iter - v.begin() - 1;//upper_bound()返回的是大于tmp的第一个值
                if(pos == -1 || v[pos].r < x)
                    puts("Reject Free");
                else{
                    printf("Free from %d to %d\n", v[pos].l, v[pos].r);
                    updata(0, v[pos].l, v[pos].r, 1);
                    v.erase(v.begin()+pos);//删除
                }
            }
            if(a[0] == 'G'){
                scanf("%d",&x);
                if(x > v.size())
                    puts("Reject Get");
                else
                    printf("Get at %d\n",v[x-1].l);//vector是从0开始的
            }
            if(a[0] == 'R'){
                updata(0, 1, n, 1);
                v.clear();
                puts("Reset Now");
            }
        }
        printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值