POJ P3667 Hotel——solution

时间:2021-05-02 00:21:02

Description

The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Street as their vacation residence. This immense hotel has N (1 ≤ N ≤ 50,000) rooms all located on the same side of an extremely long hallway (all the better to see the lake, of course).

The cows and other visitors arrive in groups of size Di (1 ≤ Di ≤ N) and approach the front desk to check in. Each group i requests a set of Di contiguous rooms from Canmuu, the moose staffing the counter. He assigns them some set of consecutive room numbers r..r+Di-1 if they are available or, if no contiguous set of rooms is available, politely suggests alternate lodging. Canmuu always chooses the value of r to be the smallest possible.

Visitors also depart the hotel from groups of contiguous rooms. Checkout i has the parameters Xi and Di which specify the vacating of rooms Xi ..Xi +Di-1 (1 ≤ Xi ≤ N-Di+1). Some (or all) of those rooms might be empty before the checkout.

Your job is to assist Canmuu by processing M (1 ≤ M < 50,000) checkin/checkout requests. The hotel is initially unoccupied.

                              --by POJ

http://poj.org/problem?id=3667



给定初始值全0的区间[1,n],支持两种操作:
1 w //查询整个区间最左端长度为w的连续0区间,输出其左端点,并把她全变成1,不存在,则输出0
2 l len //把以l为左端点长度为len的区间清零
 
考虑线段树维护区间:
max:区间最长连续0;
lmax:区间左起最长连续0;
rmax:区间右起最长连续0;
然后把1操作拆成先查询再在此基础上修改,这样修改可与2操作共用函数
查询时
优先递归左半区间,
左区间max非法,则查询左区间rmax+右区间lmax,
再非法,则递归右半区间,
再非法,则返回0,
修改则走线段树正常区间修改流程,打标记什么的;
注意如果查询失败,记得不能进行修改;
然后,如果查到了单点,记得特判一下;
一开始,我想当然的想为1操作定义一个函数,为2操作定义一个函数;
这样第一个函数一边查询一边修改
然而这样就需要打各种各样修改位置不同的标记——因为查询的递归与修改的递归流程很不相似
废了好久,
然后才知道可以这样定函数,
重构,然后清晰了许多;
代码能力不够啊;
代码如下:
 #include<cstdio>
using namespace std;
int n,m,L,R;
struct tree{
int lmax,rmax,max,lz;
}line[];
void builine(int ,int ,int );
void up(int ,int ,int );
void down(int ,int ,int );
int search(int ,int ,int ,int );
void change(int ,int ,int ,int );
int main()
{
int i,j,k,ans;
scanf("%d%d",&n,&m);
builine(,n,);
for(i=;i<=m;i++){
scanf("%d",&j);
if(j==){
scanf("%d",&k);
ans=search(,n,,k);
printf("%d\n",ans);
L=ans;R=L+k-;
if(L)
change(,n,,);
}
else{
scanf("%d%d",&L,&k);
R=L+k-;
change(,n,,);
}
}
}
void builine(int l,int r,int nu){
if(l==r){
line[nu].lmax=line[nu].rmax=line[nu].max=;
return ;
}
int mid=(l+r)>>;
builine(l,mid,nu<<);
builine(mid+,r,nu<<|);
line[nu].lmax=line[nu].rmax=line[nu].max=line[nu<<].max+line[nu<<|].max;
}
void up(int l,int r,int nu){
int mid=(l+r)>>;
if(line[nu<<].max>line[nu<<|].max)
line[nu].max=line[nu<<].max;
else
line[nu].max=line[nu<<|].max;
if(line[nu].max<line[nu<<].rmax+line[nu<<|].lmax)
line[nu].max=line[nu<<].rmax+line[nu<<|].lmax;
line[nu].lmax=line[nu<<].lmax==(mid-l+)?line[nu<<].lmax+line[nu<<|].lmax:line[nu<<].lmax;
line[nu].rmax=line[nu<<|].rmax==(r-mid)?line[nu<<|].rmax+line[nu<<].rmax:line[nu<<|].rmax;
}
void down(int l,int r,int nu){
int mid=(l+r)>>;
if(line[nu].lz){
line[nu<<].lmax=line[nu<<].max=line[nu<<].rmax=((line[nu].lz-)^)*(mid-l+);
line[nu<<|].lmax=line[nu<<|].max=line[nu<<|].rmax=((line[nu].lz-)^)*(r-mid);
line[nu<<].lz=line[nu<<|].lz=line[nu].lz;
line[nu].lz=;
}
}
int search(int l,int r,int nu,int len){
int mid=(l+r)>>,ans;
down(l,r,nu);
if(l==r)
return line[nu].max*l;
if(line[nu<<].max>=len){
ans=search(l,mid,nu<<,len);
return ans;
}
if(line[nu<<].rmax+line[nu<<|].lmax>=len){
ans=mid-line[nu<<].rmax+;
return ans;
}
if(line[nu<<|].max>=len){
ans=search(mid+,r,nu<<|,len);
return ans;
}
return ;
}
void change(int l,int r,int nu,int x){
if(L<=l&&r<=R){
line[nu].lmax=line[nu].rmax=line[nu].max=(r-l+)*(x^);
line[nu].lz=x+;
return ;
}
down(l,r,nu);
int mid=(l+r)>>;
if(L<=mid)
change(l,mid,nu<<,x);
if(R>mid)
change(mid+,r,nu<<|,x);
up(l,r,nu);
}

祝AC