poj 1823 Hotel

        题意:旅馆有n个房间,初始都是空的,有p次操作,操作1是占用房间a~a+b-1,操作2是清空房间a~a+b-1,操作3是询问最大连续空房数。

        思路:线段树(区间更新)。每个节点维护3个值,空前缀长度,空后缀长度,最大连续空房数。区间合并时就根据它们合并起来。


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;

#define maxn 16010

struct node{
	int l,r;
	int sub,pre,suf;
	bool lazy;
};

node tree[maxn<<2];

void push_down(int n){
	tree[n].lazy=0;
	tree[n*2].lazy=tree[n*2+1].lazy=1;
	if(tree[n].sub){
		tree[n*2].sub=tree[n*2].pre=tree[n*2].suf= tree[n*2].r-tree[n*2].l+1;
		tree[n*2+1].sub=tree[n*2+1].pre=tree[n*2+1].suf= tree[n*2+1].r-tree[n*2+1].l+1;
	}else{
		tree[n*2].sub=tree[n*2].pre=tree[n*2].suf= 0;
		tree[n*2+1].sub=tree[n*2+1].pre=tree[n*2+1].suf= 0;
	}
}

void push_up(node& p,node& lch,node& rch){
	p.sub=max(lch.suf+rch.pre, max(lch.sub,rch.sub) );
	if(lch.sub==lch.r-lch.l+1){
		p.pre=lch.sub+rch.pre;
	}else{
		p.pre=lch.pre;
	}
	if(rch.sub==rch.r-rch.l+1){
		p.suf=rch.sub+lch.suf;
	}else{
		p.suf=rch.suf;
	}
}

void build_tree(int n,int l,int r){
	tree[n].l=l; tree[n].r=r;
	tree[n].sub=tree[n].pre=tree[n].suf=r-l+1;
	tree[n].lazy=0;
	if(l==r){
		return;
	}
	int mid=(l+r)>>1;
	build_tree(n*2,l,mid);
	build_tree(n*2+1,mid+1,r);
}

void update(int n,int l,int r,bool f){
	if(tree[n].l==l&&tree[n].r==r){
		tree[n].lazy=1;
		if(f){
			tree[n].pre=tree[n].suf=tree[n].sub=0;
		}else{
			tree[n].pre=tree[n].suf=tree[n].sub=r-l+1;
		}
		return;
	}
	
	if(tree[n].lazy)push_down(n);
	
	int mid=(tree[n].l+tree[n].r)>>1;
	if(r<=mid){
		update(n*2,l,r,f);
	}else{
		if(l>mid){
			update(n*2+1,l,r,f);
		}else{
			update(n*2,l,mid,f);
			update(n*2+1,mid+1,r,f);
		}
	}
	push_up(tree[n],tree[n*2],tree[n*2+1]);
}

int main(){
	int n,p;
	while(cin>>n>>p){
		build_tree(1,1,n);
		for(int i=1;i<=p;i++){
			int op;
			scanf("%d",&op);
			if(op==1){
				int a,b;
				scanf("%d%d",&a,&b);
				b=a+b-1;
				update(1,a,b,1);
			}else if(op==2){
				int a,b;
				scanf("%d%d",&a,&b);
				b=a+b-1;
				update(1,a,b,0);
			}else{
				printf("%d\n",tree[1].sub);
			}
		}
	}
	return 0;
}


你可能感兴趣的:(线段树)