题目链接:http://poj.org/problem?id=3667
题目大意:一共有n个房间,初始时都是空的,现在有m个操作,操作有以下两种:
1.1 d :询问是否有连续d个空的房间,若有则输出连续房间的起始编号,若无则输出0
2.2 xi d:将第xi个房间至第xi+d-1个房间清空
解题思路:线段树维护区间最大连续长度,tree[cur].lm代表以区间左端点为起点的连续段的长度 tree[cur].rm代表以区间右端点为终点的连续段的长度,tree[2*cur].rm+tree[2*cur+1].lm代表包含该区间中点的连续段的长度 这是个隐含值(中间连续段),则区间内最长连续段值不止要从左右子节点的最长连续段中择最大 还要考虑该区间的中间连续段即tree[cur].len=max(tree[2*cur].rm+tree[2*cur+1].lm,max(tree[2*cur].len,tree[2*cur+1].len));
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=50007;
int n,m;
struct node{
int lm,rm,len,cov;
}tree[maxn<<2];
void pushup(int len,int rt){
tree[rt].lm=tree[rt<<1].lm;
if(tree[rt].lm==len-(len>>1)){
tree[rt].lm+=tree[rt<<1|1].lm;
}
tree[rt].rm=tree[rt<<1|1].rm;
if(tree[rt].rm==(len>>1)){
tree[rt].rm+=tree[rt<<1].rm;
}
tree[rt].len=max(tree[rt<<1].rm+tree[rt<<1|1].lm,max(tree[rt<<1].len,tree[rt<<1|1].len));
}
void pushdown(int len,int rt){
if(tree[rt].cov!=-1){
tree[rt<<1].cov=tree[rt<<1|1].cov=tree[rt].cov;
tree[rt<<1].lm=tree[rt<<1].rm=tree[rt<<1].len=tree[rt].cov?0:(len-(len>>1));
tree[rt<<1|1].lm=tree[rt<<1|1].rm=tree[rt<<1|1].len=tree[rt].cov?0:(len>>1);
tree[rt].cov=-1;
}
}
void build(int l,int r,int rt){
tree[rt].cov=-1;
tree[rt].lm=tree[rt].rm=tree[rt].len=r-l+1;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}
void update(int L,int R,int val,int l,int r,int rt){
if(L<=l&&R>=r){
tree[rt].cov=val;
tree[rt].lm=tree[rt].rm=tree[rt].len=val?0:(r-l+1);
return;
}
int mid=(l+r)>>1;
pushdown(r-l+1,rt);
if(L<=mid) update(L,R,val,l,mid,rt<<1);
if(R>mid) update(L,R,val,mid+1,r,rt<<1|1);
pushup(r-l+1,rt);
}
int query(int w,int l,int r,int rt){
if(l==r)return 1;
pushdown(r-l+1,rt);
int mid=(l+r)>>1;
if(tree[rt<<1].len>=w) return query(w,l,mid,rt<<1);
else if(tree[rt<<1].rm+tree[rt<<1|1].lm>=w) return mid-tree[rt<<1].rm+1;
else return query(w,mid+1,r,rt<<1|1);
}
int main(){
scanf("%d%d",&n,&m);
build(1,n,1);
while(m--){
int op,x,cnt,ans;
scanf("%d",&op);
if(op==1){
scanf("%d",&cnt);
if(tree[1].len<cnt) ans=0;
else ans=query(cnt,1,n,1);
printf("%d\n",ans);
if(ans>0)
update(ans,ans+cnt-1,1,1,n,1);
}else{
scanf("%d%d",&x,&cnt);
update(x,x+cnt-1,0,1,n,1);
}
}
return 0;
}
来源:https://www.cnblogs.com/zjl192628928/p/11673406.html