题解:节点中 lsum表示从该节点的最左端起的连续房间数, rsum 表示该节点最右端的连续房间数, sum 表示该节点内最大的连续房间数。flag == 1 表示房间全空可以入住, flag == 0 表示客满不能入住。flag == -1 表示不用向下更新。
#include<iostream> using namespace std; #define N 50003 #define L(u) ( u << 1 ) #define R(u) ( u << 1 | 1 ) #define max(a,b) ( a > b ? a : b ) struct TreeNode { int l, r, flag; int lsum, rsum, msum; void cal () { lsum = rsum = msum = (r - l + 1) * flag; } } node[N*3]; void build ( int u, int l, int r ) { node[u].r = r; node[u].l = l; node[u].flag = 1; 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 flag ) { if ( l <= node[u].l && node[u].r <= r ) { node[u].flag = flag; node[u].cal(); return; } if ( node[u].flag != -1 ) { node[L(u)].flag = node[R(u)].flag = node[u].flag; node[L(u)].cal(); node[R(u)].cal(); node[u].flag = -1; } int mid = ( node[u].l + node[u].r ) >> 1; if ( r <= mid ) update ( L(u), l, r, flag ); else if ( l > mid ) update ( R(u), l, r, flag ); else { update ( L(u), l, mid, flag ); update ( R(u), mid + 1, r, flag ); } if ( node[L(u)].lsum == node[L(u)].r - node[L(u)].l + 1 ) node[u].lsum = node[L(u)].lsum + node[R(u)].lsum; else node[u].lsum = node[L(u)].lsum; if ( node[R(u)].rsum == node[R(u)].r - node[R(u)].l + 1 ) node[u].rsum = node[L(u)].rsum + node[R(u)].rsum; else node[u].rsum = node[R(u)].rsum; //这句话是错误的node[u].msum = max ( max(node[u].lsum, node[u].rsum), node[L(u)].rsum+node[R(u)].lsum ); node[u].msum = max ( max(node[L(u)].msum, node[R(u)].msum ), node[L(u)].rsum+node[R(u)].lsum ); } int query ( int u, int num ) { if ( node[u].l == node[u].r && num == 1 ) return node[u].l; if ( node[u].flag != -1 ) { node[L(u)].flag = node[R(u)].flag = node[u].flag; node[L(u)].cal(); node[R(u)].cal(); node[u].flag = -1; } if ( node[L(u)].msum >= num ) return query ( L(u), num ); else if ( node[L(u)].rsum + node[R(u)].lsum >= num ) return node[L(u)].r - node[L(u)].rsum + 1; else if ( node[R(u)].msum >= num ) return query ( R(u), num ); return 0; } int main() { int n, m, oper, s, num; while ( scanf("%d%d",&n,&m) != EOF ) { build ( 1, 1, n ); while ( m-- ) { scanf("%d",&oper); if ( oper == 1 ) { scanf("%d",&num); s = query ( 1, num ); printf("%d\n",s); if ( s != 0 ) update ( 1, s, s+num-1, 0 ); } else { scanf("%d%d",&s,&num); update ( 1, s, s+num-1, 1 ); } } } return 0; }