您的位置:首页 > 其它

poj 3667 线段树成端更新区间最大连续和

2012-10-23 19:18 399 查看
题目描述:

输入包括n,m,n表示现在一共有n个相邻的房间,m表示有m条命令。

1 a 表示现在来了一个人数为a的队伍,需要一个连续的区间能够容纳这么多人,如果能够容纳,输入最靠左边的房间的号码,否则输出0。

2 a,b 表示清空[a,a+b-1]区间内所有的房子

解题思路:

线段树结构体,定义需要记录的三个值,最大左连续、最大右连续、最大连续。

View Code

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int N = 50005;
int mmax[N<<2],lmax[N<<2],rmax[N<<2],cover[N<<2];
void PushDown(int t,int m)
{
if(cover[t]!=-1)
{
cover[t<<1]=cover[t<<1|1]=cover[t];
mmax[t<<1]=lmax[t<<1]=rmax[t<<1]=cover[t]?0:m-(m>>1);
mmax[t<<1|1]=lmax[t<<1|1]=rmax[t<<1|1]=cover[t]?0:(m>>1);
cover[t]=-1;
}
}
void PushUp(int t,int m)
{
lmax[t]=lmax[t<<1];
if(lmax[t]==(m-(m>>1)))lmax[t]+=lmax[t<<1|1];
rmax[t]=rmax[t<<1|1];
if(rmax[t]==(m>>1))rmax[t]+=rmax[t<<1];
mmax[t]=max(mmax[t<<1],mmax[t<<1|1]);
mmax[t]=max(mmax[t],rmax[t<<1]+lmax[t<<1|1]);
}
void build(int t,int l,int r)
{
mmax[t]=lmax[t]=rmax[t]=r-l+1;
cover[t]=-1;
if(l==r) return ;
int m=(l+r)>>1;
build(t<<1,l,m);
build(t<<1|1,m+1,r);
}
int query(int t,int l,int r,int w)
{
if(l==r)return l;
PushDown(t,r-l+1);
int m=(l+r)>>1;
if(mmax[t<<1]>=w)return query(t<<1,l,m,w);
else
if(rmax[t<<1]+lmax[t<<1|1]>=w)return m-rmax[t<<1]+1;
return query(t<<1|1,m+1,r,w);
}
void update(int t,int l,int r,int L,int R,int val)
{
if(L<=l&&r<=R)
{
mmax[t]=lmax[t]=rmax[t]=val?0:r-l+1;
cover[t]=val;
return ;
}
PushDown(t,r-l+1);
int m=(l+r)>>1;
if(L<=m)update(t<<1,l,m,L,R,val);
if(R>m)update(t<<1|1,m+1,r,L,R,val);
PushUp(t,r-l+1);
}
int main()
{
int n,m,o,a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
build(1,1,n);
for(int i=0;i<m;i++)
{
scanf("%d",&o);
if(o==1)
{
scanf("%d",&a);
if(mmax[1]<a)printf("0\n");
else
{
int pos=query(1,1,n,a);
printf("%d\n",pos);
update(1,1,n,pos,pos+a-1,1);
}
}
else
{
scanf("%d%d",&a,&b);
update(1,1,n,a,a+b-1,0);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: