题目链接: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 ",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; }