您的位置:首页 > Web前端

[USACO08FEB]酒店Hotel

2017-08-24 10:08 218 查看

题目大意

一段01序列,0代表没人住,1代表有人住,住房和退房都要求是修改一段连续区间.

求能够安排住房的区间的左端点

题解

线段树

要判断能否住 要维护区间0序列长最大值.和区间0序列最左边的长度和右边长度

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;

int sum[400010],lm[400010],rm[400010],m[400010],tag[400010],n,T;

void pushup(int rt){
if(m[rt<<1]==sum[rt<<1]){
lm[rt]=m[rt<<1]+lm[rt<<1|1];
}else{
lm[rt]=lm[rt<<1];
}
if(m[rt<<1|1]==sum[rt<<1|1]){
rm[rt]=m[rt<<1|1]+rm[rt<<1];
}else{
rm[rt]=rm[rt<<1|1];
}
m[rt]=max(max(m[rt<<1],m[rt<<1|1]),rm[rt<<1]+lm[rt<<1|1]);
return;
}

void pushdown(int rt){
if(tag[rt]==0)    return;
if(tag[rt]==1){
tag[rt<<1]=tag[rt<<1|1]=1;
m[rt<<1]=lm[rt<<1]=rm[rt<<1]=0;
m[rt<<1|1]=lm[rt<<1|1]=rm[rt<<1|1]=0;
}
if(tag[rt]==2){
tag[rt<<1]=tag[rt<<1|1]=2;
m[rt<<1]=lm[rt<<1]=rm[rt<<1]=sum[rt<<1];
m[rt<<1|1]=lm[rt<<1|1]=rm[rt<<1|1]=sum[rt<<1|1];
}
tag[rt]=0;
}

void build(int rt,int l,int r){
lm[rt]=rm[rt]=m[rt]=sum[rt]=r-l+1;
tag[rt]=0;
if(l==r) return;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
return;
}

int query(int rt,int l,int r,int len){
pushdown(rt);
if(l==r)    return l;
int mid=(l+r)>>1;
if(m[rt<<1]>=len)    return query(rt<<1,l,mid,len);
if(rm[rt<<1]+lm[rt<<1|1]>=len)    return mid-rm[rt<<1]+1;
else    return query(rt<<1|1,mid+1,r,len);
}

void modify(int L,int R,int c,int rt,int l,int r){
pushdown(rt);
if((L<=l)&&(r<=R)){
if(c==1) m[rt]=lm[rt]=rm[rt]=0;
else m[rt]=lm[rt]=rm[rt]=sum[rt];
tag[rt]=c;
return;
}
int mid=(l+r)>>1;
if(L<=mid)    modify(L,R,c,rt<<1,l,mid);
if(R>mid)    modify(L,R,c,rt<<1|1,mid+1,r);
pushup(rt);
}

int main(){
scanf("%d%d",&n,&T);
build(1,1,n);
while(T--){
int opt,a,b;
scanf("%d",&opt);
if(opt==1){
scanf("%d",&a);
if(m[1]<a){printf("0\n");continue;}
int p=query(1,1,n,a);
printf("%d\n",p);
modify(p,p+a-1,1,1,1,n);
}else{
scanf("%d%d",&a,&b);
modify(a,a+b-1,2,1,1,n);
}
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: