HDU-2871-Memory Control(线段树修改,合并,查询)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871

题目大意:n个节点,4种操作:1:将所有节点置为0。2:分配一个连续x大小的空间,起始编号小的优先。3:释放包含编号x的空间。4:返回第x个空间的起始编号

思路:线段树的区间修改,合并。维护节点标记,大小,数量,左连续,右连续,最长连续。

对于操作1,根节点标记为0即可。

操作2:获得第一个长度为>=x的空间,需要用到最长连续空间。

操作3:获得x的包含区间,区间修改即可。

操作4:找到x的包含区间即可。

ACCode:

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
// srand(unsigned)time(NULL));rand();
 
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
 
#define ll long long
#define Pair pair<int,int>
#define clean(a,b) memset(a,b,sizeof(a))
using namespace std;
 
const int MAXN=5e4+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
//unsigned register
// ios::sync_with_stdio(false)

struct SegTree{
	struct Node{
		int l,r;
		int ls,rs,ms,len;
		int sp,ep,siz;
		int lazy;
	};
	Node Tree[MAXN<<2];
	
	void PushUp(int rt){
		Tree[rt].siz=Tree[rt<<1].siz+Tree[rt<<1|1].siz;
		Tree[rt].ms=max(max(Tree[rt<<1].ms,Tree[rt<<1|1].ms),Tree[rt<<1].rs+Tree[rt<<1|1].ls);
		if(Tree[rt<<1].ls==Tree[rt<<1].len) Tree[rt].ls=Tree[rt<<1].ls+Tree[rt<<1|1].ls;
		else Tree[rt].ls=Tree[rt<<1].ls;
		if(Tree[rt<<1|1].rs==Tree[rt<<1|1].len) Tree[rt].rs=Tree[rt<<1|1].rs+Tree[rt<<1].rs;
		else Tree[rt].rs=Tree[rt<<1|1].rs;
	}
	void PushDown(int rt){
		if(Tree[rt].lazy!=-1){
			Tree[rt<<1].lazy=Tree[rt<<1|1].lazy=Tree[rt].lazy;
			Tree[rt<<1].ls=Tree[rt<<1].rs=Tree[rt<<1].ms=Tree[rt].lazy?0:Tree[rt<<1].len;
			Tree[rt<<1|1].ls=Tree[rt<<1|1].rs=Tree[rt<<1|1].ms=Tree[rt].lazy?0:Tree[rt<<1|1].len;
			Tree[rt<<1].sp=Tree[rt<<1|1].sp=Tree[rt].sp;
			Tree[rt<<1].ep=Tree[rt<<1|1].ep=Tree[rt].ep;
			if(Tree[rt].lazy==0) Tree[rt<<1].siz=Tree[rt<<1|1].siz=0;
			Tree[rt].lazy=-1;
		}
	}
	void Build(int l,int r,int rt){
		Tree[rt].l=l;Tree[rt].r=r;
		Tree[rt].ls=Tree[rt].rs=Tree[rt].ms=Tree[rt].len=r-l+1;
		Tree[rt].sp=Tree[rt].ep=Tree[rt].siz=0;
		Tree[rt].lazy=-1;
		if(l==r) return ;
		int mid=(l+r)>>1;
		Build(l,mid,rt<<1);Build(mid+1,r,rt<<1|1);
	}
	void Update(int ql,int qr,int val,int rt){//区间修改 
		if(ql<=Tree[rt].l&&Tree[rt].r<=qr){
			if(val){//给区间设为1 
				if(Tree[rt].l==ql) Tree[rt].siz++;
				Tree[rt].ls=Tree[rt].rs=Tree[rt].ms=0;
				Tree[rt].sp=ql;Tree[rt].ep=qr;
				Tree[rt].lazy=1;
				return ;
			}
			else{//区间设为0 
				if(Tree[rt].l==ql) Tree[rt].siz--;
				Tree[rt].ls=Tree[rt].rs=Tree[rt].ms=Tree[rt].len;
				Tree[rt].sp=Tree[rt].ep=0;
				Tree[rt].lazy=0;
				return ;
			}
		}PushDown(rt);
		//int mid=(Tree[rt].l+Tree[rt].r)>>1;
		if(qr<=Tree[rt<<1].r) Update(ql,qr,val,rt<<1);
		else if(ql>=Tree[rt<<1|1].l) Update(ql,qr,val,rt<<1|1);
		else{
			Update(ql,qr,val,rt<<1);
			Update(ql,qr,val,rt<<1|1);
		}PushUp(rt);
	}
	int QueryX(int x,int rt){//查询长度为x的区间 
		if(Tree[rt].ms==Tree[rt].len) return Tree[rt].l;
		PushDown(rt);
		if(Tree[rt<<1].ms>=x) return QueryX(x,rt<<1);
		else if(Tree[rt<<1].rs&&Tree[rt<<1].rs+Tree[rt<<1|1].ls>=x) return Tree[rt<<1].r-Tree[rt<<1].rs+1;
		else return QueryX(x,rt<<1|1);
	}
	Pair QueryPos(int Pos,int rt){//查询Pos所在位置的区间 
		if(Tree[rt].sp) return make_pair(Tree[rt].sp,Tree[rt].ep);
		if(Tree[rt].l==Tree[rt].r) return make_pair(-1,-1);
		PushDown(rt);
		if(Pos<=Tree[rt<<1].r) return QueryPos(Pos,rt<<1);
		else return QueryPos(Pos,rt<<1|1);
	}
	int QueryK(int k,int rt){//查询第k个区间 
		if(Tree[rt].sp) return Tree[rt].sp;
		PushDown(rt);
		if(Tree[rt<<1].siz>=k) return QueryK(k,rt<<1);
		else return QueryK(k-Tree[rt<<1].siz,rt<<1|1);
	}
	void Show(int rt){
		printf("l=%d,r=%d,ls=%d,rs=%d,ms=%d,sp=%d,ep=%d,siz=%d\n",Tree[rt].l,Tree[rt].r,Tree[rt].ls,Tree[rt].rs,Tree[rt].ms,Tree[rt].sp,Tree[rt].ep,Tree[rt].siz);
		if(Tree[rt].l==Tree[rt].r) return ;
		Show(rt<<1);Show(rt<<1|1);
	}
};
SegTree Seg;
int n,m;

int main(){
	while(~scanf("%d%d",&n,&m)){
		Seg.Build(1,n,1);
		while(m--){
			char opt[15];scanf("%s",&opt);
			if(opt[0]=='N'){//申请长度x的新节点 
				int x;scanf("%d",&x);
				if(Seg.Tree[1].ms<x) printf("Reject New\n");
				else{
					int l=Seg.QueryX(x,1);
					int r=l+x-1;
					Seg.Update(l,r,1,1);
					printf("New at %d\n",l);
				}
			}
			else if(opt[0]=='F'){//释放包含x节点的区间 
				int x;scanf("%d",&x);
				Pair Pos=Seg.QueryPos(x,1);
				if(Pos.first==-1) printf("Reject Free\n");
				else{
					Seg.Update(Pos.first,Pos.second,0,1);
					printf("Free from %d to %d\n",Pos.first,Pos.second);
				}
			}
			else if(opt[0]=='G'){//获得第x个的首位置 
				int x;scanf("%d",&x);
				if(Seg.Tree[1].siz<x) printf("Reject Get\n");
				else printf("Get at %d\n",Seg.QueryK(x,1));
			}
			else{
				Seg.Update(1,n,0,1);Seg.Tree[1].siz=0;
				printf("Reset Now\n");
			}//Seg.Show(1);
		}printf("\n");
	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值