题目链接 https://cn.vjudge.net/problem/POJ-3667
【题意】
有
个连续房间,
次操作,操作分两种类型
占据一段长度为
的连续空房间,若有多个满足,尽量选择靠左的,输出选择区间的起点,找不出则输出
把以房间
开始的长度为
的连续房间全部清空
下标均从
开始,
【思路】
线段树区间合并,线段树维护区间的三个值,一个是
,表示区间左端为起点向右最长的连续空房间长度,另一个是
,表示区间右端点为终点向左最长的连续空房间长度,最后一个是
表示这段区间内最长的连续空房间长度,这三个值都可以在已知左右子节点的情况下推算出当前节点. 用
标记区间更新,查询时单点查询,满足条件时尽量让区间靠左
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define node tree[id]
#define lson tree[id<<1]
#define rson tree[id<<1|1]
using namespace std;
const int maxn=50005;
struct Tree{
int left,right;
int sum,sumL,sumR;
int lazy;
}tree[maxn<<2];
int n,q;
void pushup(int id){
if(lson.sumL==lson.right-lson.left+1)
node.sumL=lson.sumL+rson.sumL;
else
node.sumL=lson.sumL;
if(rson.sumR==rson.right-rson.left+1)
node.sumR=rson.sumR+lson.sumR;
else
node.sumR=rson.sumR;
node.sum=lson.sumR+rson.sumL;
if(lson.sum>node.sum) node.sum=lson.sum;
if(rson.sum>node.sum) node.sum=rson.sum;
}
void pushdown(int id){
if(node.lazy!=-1 && node.left!=node.right){
lson.sum=lson.sumL=lson.sumR=node.lazy?(lson.right-lson.left+1):0;
lson.lazy=node.lazy;
rson.sum=rson.sumL=rson.sumR=node.lazy?(rson.right-rson.left+1):0;
rson.lazy=node.lazy;
node.lazy=-1;
}
}
void build(int id,int le,int ri){
node.left=le;
node.right=ri;
node.sum=node.sumL=node.sumR=ri-le+1;
node.lazy=-1;
if(le==ri) return;
int mid=(le+ri)>>1;
build(id<<1,le,mid);
build(id<<1|1,mid+1,ri);
}
void update(int id,int le,int ri,int val){
if(node.left==le && node.right==ri){
node.sum=node.sumL=node.sumR=val?(node.right-node.left+1):0;
node.lazy=val;
return;
}
pushdown(id);
int mid=(node.left+node.right)>>1;
if(ri<=mid) update(id<<1,le,ri,val);
else if(le>mid) update(id<<1|1,le,ri,val);
else{
update(id<<1,le,mid,val);
update(id<<1|1,mid+1,ri,val);
}
pushup(id);
}
int query(int id,int val){
if(node.left==node.right){
return node.left;
}
pushdown(id);
if(lson.sum>=val)
return query(id<<1,val);
else if(lson.sumR+rson.sumL>=val)
return rson.left-lson.sumR;
else
return query(id<<1|1,val);
}
int main(){
while(scanf("%d%d",&n,&q)==2){
build(1,1,n);
while(q--){
int op;
scanf("%d",&op);
if(op==1){
int x;
scanf("%d",&x);
if(tree[1].sum<x) puts("0");
else{
int ans=query(1,x);
printf("%d\n",ans);
update(1,ans,ans+x-1,0);
}
}
else{
int x,y;
scanf("%d%d",&x,&y);
update(1,x,x+y-1,1);
}
}
}
return 0;
}