POJ 1823 Hotel
http://poj.org/problem?id=1823
题意:
一个旅馆,有n间连续的房间,现在有p组操作:
type 1: '1, a, b': 第a个房间起的b个房间有旅客入住。(即更新[a,a+b-1]这段区间)
type 2: '2, a, b': 第a个房间起的b个房间的旅客离开。
type 3: '3': 问最长的连续空房间有多少间。
数据:
N (3 <= N <= 16 000)
P (3 <= P <= 200 000)
Time Limit: 5000MS
思路:
1. 线段树.
2. 区间中的信息包含 从最左侧开始连续的最值,从最右侧开始连续的最值,区间的最值(为了便于子区间到父区间的更新).
3. 查询则只需查找全区间.
代码:
/*
题意:一个hotel,有n间连续的房间,现在有m组操作:
type 1: '1, a, b': 第a个房间起的b个房间有旅客入住。
type 2: '2, a, b': 第a个房间起的b个房间的旅客离开。
type 3: '3': 问最长的连续空房间有多少间。
思路:线段树。线段树递归的性质,在递归回来的时候,
由于左右子结点性质的改变,即时对父结点信息进行相应的更改。
*/
#include <iostream>
#include <string.h>
#include <math.h>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
const int N = 20005;
const int M = 1000000007 ;
// const double Pi = acos(-1);
// const LL INF = 1<<32;
int n,m,cc;
int a,b,c;
struct nd
{
int l,r;
int cov; //1表示这个区间的房间全住人,-1表示全空,0表示有空用住
int lm,rm,ma; //lm表示区间从左侧开始连续的做多空房
}tr[N*4];
void build(int l,int r,int rt)
{
tr[rt].l=l;
tr[rt].r=r;
if (l==r)
return;
int mid = (l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}
void pushdown(int rt,int op)
{
tr[rt].cov=0;
tr[rt<<1].cov=op;
tr[rt<<1|1].cov=op;
if (op==1)
{
tr[rt<<1].lm=tr[rt<<1].rm=tr[rt<<1].ma=0;
tr[rt<<1|1].lm=tr[rt<<1|1].rm=tr[rt<<1|1].ma=0;
}
else
{
int len;
len = tr[rt<<1].r - tr[rt<<1].l + 1;
tr[rt<<1].lm=tr[rt<<1].rm=tr[rt<<1].ma=len;
len = tr[rt<<1|1].r - tr[rt<<1|1].l + 1;
tr[rt<<1|1].lm=tr[rt<<1|1].rm=tr[rt<<1|1].ma=len;
}
}
void update(int l,int r,int op,int rt) //op表示状态
{
if (l<=tr[rt].l && r>=tr[rt].r)
{
tr[rt].cov=op;
if (op==1)
tr[rt].lm=tr[rt].rm=tr[rt].ma=0;
else
{
int len=tr[rt].r-tr[rt].l+1;
tr[rt].lm=tr[rt].rm=tr[rt].ma=len;
}
return;
}
if (tr[rt].cov==op)
return;
if (tr[rt].cov==-op)
pushdown(rt,-op);
if (r<=tr[rt<<1].r)
update(l,r,op,rt<<1);
else if (l>=tr[rt<<1|1].l)
update(l,r,op,rt<<1|1);
else
{
update(l,r,op,rt<<1);
update(l,r,op,rt<<1|1);
}
//递归结束
if (tr[rt<<1].cov==-1)
tr[rt].lm=tr[rt<<1].ma+tr[rt<<1|1].lm;
else
tr[rt].lm=tr[rt<<1].lm;
if (tr[rt<<1|1].cov==-1)
tr[rt].rm=tr[rt<<1|1].ma+tr[rt<<1].rm;
else
tr[rt].rm=tr[rt<<1|1].rm;
int a=tr[rt<<1].rm+tr[rt<<1|1].lm;
int b=max(tr[rt<<1].ma,tr[rt<<1|1].ma);
int c=max(tr[rt<<1].lm,tr[rt<<1|1].rm);
tr[rt].ma=max(max(a,b),c);
//更新root状态
if (tr[rt<<1].cov==tr[rt<<1|1].cov)
tr[rt].cov=tr[rt<<1].cov;
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
memset(tr,0,sizeof(tr));
build(1,n,1);
tr[1].cov=-1;
tr[1].ma=n;
for (int i=0;i<m;i++)
{
scanf("%d",&a);
if (a==1)
{
scanf("%d%d",&b,&c);
update(b,b+c-1,1,1);
}
else if (a==2)
{
scanf("%d%d",&b,&c);
update(b,b+c-1,-1,1);
}
else
printf("%d\n",tr[1].ma);
}
}
return 0;
}
/*
12 10
3
1 2 3
1 9 4
3
2 2 1
3
2 9 2
3
2 3 2
3
*/
//Ans : 12 4 4 6 10