[P2894][USACO08FEB] 酒店Hotel (线段树+懒标记下传)
Posted nnezgy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[P2894][USACO08FEB] 酒店Hotel (线段树+懒标记下传)相关的知识,希望对你有一定的参考价值。
题意:有 n个房间,题目给出两个操作,若 op==1,就输出最靠左的连续空房数量为 x的房间序列的最左边的序号,然后将这些房间改为入住;若 op==2,就将从 x~y的的序列全部改为空房;
解法:线段树+懒标记下传;
1.线段树;题目让在一个很长的序列操作很多次,暴力显然过不了,要用线段树优化;
2.懒标记下传;这是本题的精髓。 此题要维护的不是序列上的数值总和,而是该序列的最长连续空房的长度 sum,从该节点从左向右数最长的连续空房长度 lm,以及从该节点从右向左数最长的连续空房长度 rm;同时还要注意在合并区间时的操作;( tag==1表示要将序列变为空房; tag==2表示要将序列变为有房)
附上代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define mid ((l+r)>>1) #define ls (o*2) #define rs (o*2+1) using namespace std; const int N = 5e4+10; inline int read() int ref=0,x=1;char ch=getchar(); while(!isdigit(ch))if(ch==‘-‘)x=-1;ch=getchar(); while(isdigit(ch))ref=ref*10+ch-‘0‘;ch=getchar(); return ref*x; int n,m; struct tree int sum,lm,rm,len; a[N<<4]; int tag[N<<4]; void pushup(int o) a[o].lm=(a[ls].lm==a[ls].len)?a[ls].len+a[rs].lm:a[ls].lm; a[o].rm=(a[rs].rm==a[rs].len)?a[rs].len+a[ls].rm:a[rs].rm; a[o].sum=max(max(a[ls].sum,a[rs].sum),a[ls].rm+a[rs].lm); void pushdown(int o) if(!tag[o]) return ; tag[ls]=tag[rs]=tag[o]; a[ls].sum=a[ls].lm=a[ls].rm=(tag[o]==1)?a[ls].len:0; a[rs].sum=a[rs].lm=a[rs].rm=(tag[o]==1)?a[rs].len:0; tag[o]=0; void build(int o,int l,int r) a[o].len=a[o].lm=a[o].rm=a[o].sum=r-l+1; if(l==r) return ; build(ls,l,mid); build(rs,mid+1,r); void updata(int o,int l,int r,int x,int y,int lz) if(x<=l&&y>=r) a[o].sum=a[o].lm=a[o].rm=(lz==1)?a[o].len:0; tag[o]=lz; return ; pushdown(o); if(x<=mid) updata(ls,l,mid,x,y,lz); if(y>mid) updata(rs,mid+1,r,x,y,lz); pushup(o); int query(int o,int l,int r,int lenth) pushdown(o); if(l==r) return l; if(a[ls].sum>=lenth) return query(ls,l,mid,lenth); if(a[ls].rm+a[rs].lm>=lenth) return mid-a[ls].rm+1; else return query(rs,mid+1,r,lenth); int main() scanf("%d%d",&n,&m); build(1,1,n); for(int i=1;i<=m;i++) int x,y,op; op=read(); if(op==1) x=read(); if(a[1].sum>=x) int ans=query(1,1,n,x); printf("%d\n",ans); updata(1,1,n,ans,ans+x-1,2); else printf("0\n"); else x=read(),y=read(); updata(1,1,n,x,x+y-1,1); return 0;
以上是关于[P2894][USACO08FEB] 酒店Hotel (线段树+懒标记下传)的主要内容,如果未能解决你的问题,请参考以下文章
[P2894][USACO08FEB] 酒店Hotel (线段树+懒标记下传)