题意:旅馆有三种操作:1入住,同时给你两个数i,M,其中i表示连续房间的起始房号,M表示房间数量;2退房,同时给你两个数i,M,其中i表示连续房间的起始房号;3查询,要求输出整个旅馆中,房号相连的最大空房间数量。
此题和3667颇为相似。
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 20003
#define L(u) (u<<1)
#define R(u) (u<<1|1)
struct TreeNode
{
int l, r, mark; //0全空,1表示住满,-1表示混杂
int lsum, rsum, msum;
void cal ()
{
if(mark == 0) lsum = rsum = msum = r - l + 1;
else if(mark == 1) lsum = rsum = msum = 0;
}
} node[MAXN*3];
void build(int u, int l, int r)
{
node[u].r = r;
node[u].l = l;
node[u].mark = 0;
node[u].cal();
if (l == r) return;
int mid = (l + r) >> 1;
build(L(u), l, mid);
build(R(u), mid + 1, r);
}
void update(int u, int l, int r, int oper)
{
if (l == node[u].l && node[u].r == r)
{
if(oper == 1) node[u].mark = 1;
else node[u].mark = 0;
node[u].cal();
return;
}
if(node[u].mark == 0 && oper == 2) return;
if(node[u].mark == 1 && oper == 1) return;
if(node[u].mark != -1)
{
node[L(u)].mark = node[R(u)].mark = node[u].mark;
node[L(u)].cal();
node[R(u)].cal();
node[u].mark = -1;
}
int mid = (node[u].l + node[u].r) >> 1;
if(r <= mid) update(L(u), l, r, oper);
else if(l > mid) update(R(u), l, r, oper);
else update(L(u), l, mid, oper), update(R(u), mid+1, r, oper);
if(node[L(u)].mark == 0)
node[u].lsum = node[L(u)].lsum + node[R(u)].lsum;
else node[u].lsum = node[L(u)].lsum;
if(node[R(u)].mark == 0)
node[u].rsum = node[L(u)].rsum + node[R(u)].rsum;
else node[u].rsum = node[R(u)].rsum;
node[u].msum = max(node[L(u)].msum, node[R(u)].msum);
node[u].msum = max(node[u].msum, node[L(u)].rsum+node[R(u)].lsum);
if(node[L(u)].mark == node[R(u)].mark)
node[u].mark = node[L(u)].mark;
else node[u].mark = -1;
}
int main()
{
int n, p, i, m, c;
scanf("%d%d",&n,&p);
build(1, 1, n);
while(p--)
{
scanf("%d",&c);
if(c != 3)
{
scanf("%d%d",&i,&m);
update(1, i, i+m-1, c);
}
else printf("%d\n",node[1].msum);
}
return 0;
}