hdu2871 Memory Control 线段树区间合并+STL删除插入

题意:有n个连续的内存单位编号从1到n。有4种操作:(1)Reset 释放所有内存 (2)New x 新建一个长度为x的连续内存块 (尽可能左),

输出内存块的最左端 (3)Free x 释放编号为x的内存单位所在的内存块,输出内存块的区间左右端 (4) Get x 获取从左往右的第x个内

存块,输出内存块的最左端。

思路:线段树区间合并。和poj3667相似,。线段树维护四个信息:(1) 区间连续为空最长长度   (2) 从区间左端连续空最长长度 

(3) 从区间右端向左连续空的最长长度  ( 4 )区间的懒惰标记  push_down更新左右子树的4个信息,push_up用更新左右子树更新根区

间。对于每次New x,记录新建内存块的左右端存入结构体插入vec,找插入的位置需要二分。 对于每次Free x,在vec中二分查找x

所在的位置(注意:因为可能存在非法输入,所以要用upper_bound找,而不能用lower_bound,请读者自己思考)如果找到,删除该

内存块。对于Reset直接对[1,n]打上懒惰标记 。 对于Get x,直接根据下标在vec找对应的内存块就行。详见代码:


// file name: hdu2871.cpp //
// author: kereo //
// create time:  2014年09月09日 星期二 21时34分28秒 //
//***********************************//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=50000+100;
const int inf=0x3fffffff;
const int mod=1000000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
int n,m;
struct block{
	int st,ed;
};
vector<block>vec;
int  cmp(block a,block b){
	return a.st<b.st;
}
struct node
{
	int l,r,c;//c=0,表示当前区间为空;c=1,表示当前区间满;c=-1,表示初始状态
	int len,ls,rs;//len记录区间最长连续空的长度,ls记录从区间左端向右连续空的长度,rs记录从区间右端向左连续空的长度
}segtree[MAXN<<2];
void push_down(int rt){
	if(segtree[rt].c!=-1){
		segtree[L(rt)].c=segtree[R(rt)].c=segtree[rt].c;
		segtree[L(rt)].ls=segtree[L(rt)].rs=segtree[L(rt)].len=segtree[rt].c ?  0 : segtree[L(rt)].r-segtree[L(rt)].l+1;
		segtree[R(rt)].ls=segtree[R(rt)].rs=segtree[R(rt)].len=segtree[rt].c ?  0 : segtree[R(rt)].r-segtree[R(rt)].l+1;
		segtree[rt].c=-1;
	}
}
void push_up(int rt){
	segtree[rt].ls=segtree[L(rt)].ls; segtree[rt].rs=segtree[R(rt)].rs;
	segtree[rt].len=max(segtree[L(rt)].len,segtree[R(rt)].len);
	if(segtree[L(rt)].ls == segtree[L(rt)].r-segtree[L(rt)].l+1)
		segtree[rt].ls+=segtree[R(rt)].ls;
	if(segtree[R(rt)].rs == segtree[R(rt)].r-segtree[R(rt)].l+1)
		segtree[rt].rs+=segtree[L(rt)].rs;
	segtree[rt].len=max(segtree[rt].len,segtree[L(rt)].rs+segtree[R(rt)].ls);

}
void build(int rt,int l,int r){
	segtree[rt].l=l;segtree[rt].r=r;
	segtree[rt].c=-1; segtree[rt].ls=segtree[rt].rs=segtree[rt].len=r-l+1;
	if(l == r) return ;
	int mid=(l+r)>>1;
	build(L(rt),l,mid); build(R(rt),mid+1,r);
}
void update(int rt,int l,int r,int c){
	if(segtree[rt].l == l && segtree[rt].r == r){
		segtree[rt].c=c;
		segtree[rt].ls=segtree[rt].rs=segtree[rt].len=segtree[rt].c ? 0 : segtree[rt].r-segtree[rt].l+1;
		return ;
	}
	push_down(rt);
	int mid=(segtree[rt].l+segtree[rt].r)>>1;
	if(r<=mid)
		update(L(rt),l,r,c);
	else if(l>mid)
		update(R(rt),l,r,c);
	else{
		update(L(rt),l,mid,c); update(R(rt),mid+1,r,c);
	}
	push_up(rt);
}
int query(int rt,int len){
	if(segtree[rt].len<len)
		return -1; // 剪枝
	if(segtree[rt].l == segtree[rt].r)
		return segtree[rt].l;
	push_down(rt);
	int mid=(segtree[rt].l+segtree[rt].r)>>1;
	if(segtree[L(rt)].len>=len)
		return query(L(rt),len);
	else if(segtree[L(rt)].rs+segtree[R(rt)].ls>=len)
		return mid-segtree[L(rt)].rs+1;
	return query(R(rt),len);
}
int main()
{
	while(~scanf("%d%d",&n,&m)){
		build(1,1,n);
		vec.clear();
		char str[10];
		while(m--){
			int x;
			scanf("%s",str);
			if(str[0] == 'N'){
				scanf("%d",&x);
				int pos=query(1,x);
				if(pos == -1)
					printf("Reject New\n");
				else {
					printf("New at %d\n",pos);
					update(1,pos,pos+x-1,1);
					block b;
					b.st=pos; b.ed=pos+x-1;
					vector<block>::iterator it;
					it=upper_bound(vec.begin(),vec.end(),b,cmp);
					vec.insert(it,b);
				}
			}
			else if(str[0] == 'F'){
				scanf("%d",&x);
				block b;
				b.st=b.ed=x;
				vector<block>::iterator it;
				it=upper_bound(vec.begin(),vec.end(),b,cmp);
				int tmp=it-vec.begin()-1;
				if(tmp == -1 || vec[tmp].ed<x)
					printf("Reject Free\n");
				else{
					printf("Free from %d to %d\n",vec[tmp].st,vec[tmp].ed);
					update(1,vec[tmp].st,vec[tmp].ed,0);
					vec.erase(vec.begin()+tmp);
				}
			}
			else if(str[0] == 'R'){
				update(1,1,n,0);
				vec.clear(); //vec要清零
				printf("Reset Now\n");
			}
			else{
				scanf("%d",&x);
				if(x>vec.size())
					printf("Reject Get\n");
				else 
					printf("Get at %d\n",vec[x-1].st);
			}
		}
		printf("\n");
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值