题目链接:http://poj.org/problem?id=3667
题意:旅馆的N(1 ≤ n ≤ 50,000) 个房间初始时全为空。现在有M(1 ≤ m < 50,000) 个操作,分为两种:
(1)1 X,要求得到连续的X个房间,输出X个连续房间的最小编号;如果有多个X的连续房间,输出编号最小的一个;不存在输出0;
(2)2 X Y,将X开始的连续Y个房间退掉。
思路:节点设置本区间最大连续空闲区间,以及从左侧、右侧开始的连续最大空闲空间。更新时注意:
本区间不包含更新区间且本区间满或空时,要将这种状态传递给子区间;
更新返回时用左右子区间的状态更新本区间。
#include <cstdio>
#include <iostream>
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
struct Node
{
int left,right,len;
int maxlen; //该结点内最长的连续空房间
int leftlen,rightlen;//该结点内左端点开始的最长连续空房间
//右端点结束的最长连续空房间
void init (int state)
{
len=right-left+1;
maxlen=state*len;
leftlen=maxlen;
rightlen=maxlen;
}
};
Node a[200005];
int n,m;
void Build (int left,int right,int t)
{
a[t].left=left;
a[t].right=right;
a[t].init(1);
if (a[t].left==a[t].right)
return;
int mid=(left+right)>>1;
Build (left,mid,2*t);
Build (mid+1,right,2*t+1);
}
int Query (int need,int t)
{
//如果该结点的最大空长度都不能满足,返回0
if (a[t].maxlen<need) return 0;
//如果左侧最大空长度满足,则返回left
if (a[t].leftlen>=need) return a[t].left;
//该节点的左侧不满足,检查左孩子
//左孩子的最大空长度满足,则答案一定在左孩子中
if (a[2*t].maxlen>=need) return Query (need,2*t);
//左孩子右边和右孩子左边加起来满足
if (a[2*t].rightlen+a[2*t+1].leftlen>=need)
return a[2*t].right-a[2*t].rightlen+1;
//以上条件都不满足,检查右孩子是否满足
return Query (need,2*t+1);
}
void Push_down (int t)
{
//[left,right]不能完全覆盖该区间,假如该区间以前满或空
//则将这种状态传给左右孩子
if (a[t].maxlen==a[t].len || a[t].maxlen==0)
{
int st=(a[t].maxlen!=0);
a[2*t].init(st);
a[2*t+1].init(st);
}
}
void Push_up (int t)
{
a[t].leftlen=a[2*t].leftlen;
if (a[t].leftlen == a[2*t].right-a[2*t].left+1)
a[t].leftlen+=a[2*t+1].leftlen;
a[t].rightlen=a[2*t+1].rightlen;
if (a[t].rightlen == a[2*t+1].right-a[2*t+1].left+1)
a[t].rightlen+=a[2*t].rightlen;
int x=t*2,y=t*2+1;
a[t].maxlen=max(a[x].maxlen,a[y].maxlen);
a[t].maxlen=max(a[t].maxlen,max(a[t].leftlen,a[t].rightlen));
a[t].maxlen=max(a[t].maxlen,a[x].rightlen+a[y].leftlen);
/*第一次写的时候上面三行如下,貌似写得不对,本题可过,Hdu4553过不了
a[t].maxlen=a[2*t].rightlen+a[2*t+1].leftlen;
a[t].maxlen=max(a[2*t].maxlen,a[t].maxlen);
a[t].maxlen=max(a[2*t+1].maxlen,a[t].maxlen);*/
}
//将区间[left,right]的状态更新为state
void Update (int left,int right,int t,int state)
{
//[left,right]能完全覆盖该区间,更新后返回
if (a[t].left>=left && a[t].right<=right)
{
a[t].init(state);
return;
}
int mid=(a[t].left+a[t].right)>>1;
Push_down (t); //更新孩子
if (right<=mid)
Update (left,right,2*t,state);
else if (left>mid)
Update (left,right,2*t+1,state);
else
{
Update (left,mid,2*t,state);
Update (mid+1,right,2*t+1,state);
}
Push_up (t);
}
int main ()
{
scanf("%d%d",&n,&m);
Build (1,n,1);
int flag,s,e;
for (int i=1;i<=m;i++)
{
scanf("%d",&flag);
if (flag==1)
{
scanf("%d",&s);
int temp=Query(s,1);
printf("%d\n",temp);
if (temp)
Update(temp,temp+s-1,1,0);
}
else
{
scanf("%d%d",&s,&e);
Update(s,s+e-1,1,1);
}
}
return 0;
}
Hdu 4553
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553
和上面那道题差不多,多记录一组状态。
#include <cstdio>
#include <iostream>
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
struct Node
{
int left,right,len;
int dmlen,nmlen;
int dl,dr,nl,nr;
void init_d (int state)
{
dmlen=state*len;
dl=dmlen;
dr=dmlen;
}
void init_n (int state)
{
nmlen=state*len;
nl=nmlen;
nr=nmlen;
}
}a[100005*4];
int n,m;
void Build (int left,int right,int t)
{
a[t].left=left;
a[t].right=right;
a[t].len=right-left+1;
a[t].init_d (1);
a[t].init_n (1);
if (a[t].left==a[t].right)
return;
int mid=(left+right)>>1;
Build (left,mid,2*t);
Build (mid+1,right,2*t+1);
}
int Query_d (int need,int t)
{
if (a[t].dmlen<need) return 0;
if (a[t].dl>=need) return a[t].left;
if (a[2*t].dmlen>=need) return Query_d (need,2*t);
if (a[2*t].dr+a[2*t+1].dl>=need)
return a[2*t].right-a[2*t].dr+1;
return Query_d (need,2*t+1);
}
int Query_n (int need,int t)
{
if (a[t].nmlen<need) return 0;
if (a[t].nl>=need) return a[t].left;
if (a[2*t].nmlen>=need) return Query_n (need,2*t);
if (a[2*t].nr+a[2*t+1].nl>=need)
return a[2*t].right-a[2*t].nr+1;
return Query_n (need,2*t+1);
}
void Push_down (int t)
{
if (a[t].left==a[t].right)
return ;
if (a[t].dmlen==a[t].len || a[t].dmlen==0)
{
int st=(a[t].dmlen!=0);
a[2*t].init_d(st);
a[2*t+1].init_d(st);
}
if (a[t].nmlen==a[t].len || a[t].nmlen==0)
{
int st=(a[t].nmlen!=0);
a[2*t].init_n(st);
a[2*t+1].init_n(st);
}
}
void Push_up (int t)
{
if (a[t].left==a[t].right)
return ;
a[t].dl=a[2*t].dl;
if (a[t].dl == a[2*t].right-a[2*t].left+1)
a[t].dl+=a[2*t+1].dl;
a[t].dr=a[2*t+1].dr;
if (a[t].dr == a[2*t+1].right-a[2*t+1].left+1)
a[t].dr+=a[2*t].dr;
a[t].dmlen=max(a[2*t].dmlen,a[2*t+1].dmlen);
a[t].dmlen=max(a[t].dmlen,max(a[t].dl,a[t].dr));
a[t].dmlen=max(a[t].dmlen,a[2*t].dr+a[2*t+1].dl);
}
void Push_upall (int t)
{
if (a[t].left==a[t].right)
return ;
a[t].dl=a[2*t].dl;
if (a[t].dl == a[2*t].right-a[2*t].left+1)
a[t].dl+=a[2*t+1].dl;
a[t].dr=a[2*t+1].dr;
if (a[t].dr == a[2*t+1].right-a[2*t+1].left+1)
a[t].dr+=a[2*t].dr;
a[t].dmlen=max(a[2*t].dmlen,a[2*t+1].dmlen);
a[t].dmlen=max(a[t].dmlen,max(a[t].dl,a[t].dr));
a[t].dmlen=max(a[t].dmlen,a[2*t].dr+a[2*t+1].dl);
a[t].nl=a[2*t].nl;
if (a[t].nl == a[2*t].right-a[2*t].left+1)
a[t].nl+=a[2*t+1].nl;
a[t].nr=a[2*t+1].nr;
if (a[t].nr == a[2*t+1].right-a[2*t+1].left+1)
a[t].nr+=a[2*t].nr;
a[t].nmlen=max(a[2*t].nmlen,a[2*t+1].nmlen);
a[t].nmlen=max(a[t].nmlen,max(a[t].nl,a[t].nr));
a[t].nmlen=max(a[t].nmlen,a[2*t].nr+a[2*t+1].nl);
}
void Updateall (int left,int right,int t,int state)
{
if (a[t].left>=left && a[t].right<=right)
{
a[t].init_d(state);
a[t].init_n(state);
return;
}
int mid=(a[t].left+a[t].right)>>1;
Push_down (t);
if (right<=mid)
Updateall (left,right,2*t,state);
else if (left>mid)
Updateall (left,right,2*t+1,state);
else
{
Updateall (left,mid,2*t,state);
Updateall (mid+1,right,2*t+1,state);
}
Push_upall (t);
}
void Update (int left,int right,int t,int state)
{
if (a[t].left>=left && a[t].right<=right)
{
a[t].init_d(state);
return;
}
int mid=(a[t].left+a[t].right)>>1;
Push_down (t);
if (right<=mid)
Update (left,right,2*t,state);
else if (left>mid)
Update (left,right,2*t+1,state);
else
{
Update (left,mid,2*t,state);
Update (mid+1,right,2*t+1,state);
}
Push_up (t);
}
int main ()
{
#ifdef ONLINE_JUDGE
#else
freopen("read.txt","r",stdin);
#endif
int T;
scanf("%d",&T);
for (int Cas=1;Cas<=T;Cas++)
{
memset(a,0,sizeof(a));
printf("Case %d:\n",Cas);
int at,n;
scanf("%d%d",&at,&n);
Build (1,at,1);
char str[10];
for (int i=1;i<=n;i++)
{
int a,b,t;
scanf("%s",str);
if (str[0]=='S')
{
scanf("%d%d",&a,&b);
Updateall(a,b,1,1);
printf("I am the hope of chinese chengxuyuan!!\n");
}
else if (str[0]=='N')
{
scanf("%d",&a);
t=Query_d(a,1);
if (t!=0)
{
printf("%d,don't put my gezi\n",t);
Updateall(t,t+a-1,1,0);
}
else
{
t=Query_n(a,1);
if (t!=0)
{
printf("%d,don't put my gezi\n",t);
Updateall(t,t+a-1,1,0);
}
else
printf("wait for me\n");
}
}
else
{
scanf("%d",&a);
t=Query_d(a,1);
if (t!=0)
{
printf("%d,let's fly\n",t);
Update(t,t+a-1,1,0);
}
else
printf("fly with yourself\n");
}
}
}
return 0;
}