题目链接: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");
}
}