Hotel---poj3667(线段树区间问题)
题目链接:http://poj.org/problem?id=3667
题意:酒店有n个房间,现有m个团队,每个团队需要连续 d 个房间,现在有两个操作,1:需要 d 个房间,2:从 x 开始连续 d 个房间退房;
当是1的时候,需要d个房间时, 我们尽可能的找到最靠左的房间给客人,输出最左边房间的编号;
简化一下就是当是1时,让连续的最左边的区间覆盖,2时让对应的区间释放;
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define INF 0xfffffff #define N 50050 #define Lson r<<1 #define Rson r<<1|1 struct SegmentTree { int L, R, flag;///flag 表示整个操作的是覆盖1还是释放覆盖2,还是保持原样0; int lsum, rsum, sum; ///lsum区间左边(从L开始)连续最大不被覆盖的值 ///rsum区间右边(到R介绍)连续最大不被覆盖的值 ///sum整个区间连续最大不被覆盖的值 int Mid() { return (L+R)>>1;} int len() { return R-L+1; } } a[N<<2]; void Build(int r, int L, int R) { a[r].L = L, a[r].R = R, a[r].flag = 0; a[r].lsum = a[r].rsum = a[r].sum = a[r].len(); if(L == R)return ; Build(Lson, L, a[r].Mid()); Build(Rson, a[r].Mid()+1, R); } void Up(int r) { a[r].lsum = a[Lson].lsum; a[r].rsum = a[Rson].rsum;///左右区间由下面的左右区间决定; if(a[r].lsum == a[Lson].len())///当超过区间所在长度时,加上相邻的那部分; a[r].lsum += a[Rson].lsum; if(a[r].rsum == a[Rson].len()) a[r].rsum += a[Lson].rsum; a[r].sum = max(a[Lson].rsum + a[Rson].lsum, max(a[Lson].sum, a[Rson].sum));///总的最大值是这三部分的最大值; } void Down(int r) { if(a[r].L != a[r].R && a[r].flag) { a[Lson].lsum = a[Lson].rsum = a[Lson].sum = (a[r].flag == 1 ? 0 : a[Lson].len()); a[Rson].lsum = a[Rson].rsum = a[Rson].sum = (a[r].flag == 1 ? 0 : a[Rson].len()); a[Lson].flag = a[Rson].flag = a[r].flag; a[r].flag = 0; } } void Update(int r, int L, int R, int flag) { Down(r);///向下更新; if(a[r].L == L && a[r].R == R) { a[r].lsum = a[r].rsum = a[r].sum = (flag == 1 ? 0 : a[r].len()); a[r].flag = flag; return ; } ///更新子区间; if(R <= a[r].Mid()) Update(Lson, L, R, flag); else if( L > a[r].Mid()) Update(Rson, L, R, flag); else { Update(Lson, L, a[r].Mid(), flag); Update(Rson, a[r].Mid()+1, R, flag); } Up(r);///当下面发生改变改变的时候需要更新上面区间的; } int Query(int r, int num) { ///查询是按照从左到右的顺序来的 if(a[r].lsum >= num) return a[r].L;///最左边的; if(a[Lson].sum >= num) return Query(Lson, num);///左区间; if(a[Lson].rsum + a[Rson].lsum >= num)///中间区间; return a[Lson].R-a[Lson].rsum+1; return Query(Rson, num);///右区间; } int main() { int n, m, op, L, d; while(scanf("%d %d", &n, &m) != EOF) { Build(1, 1, n); while(m--) { scanf("%d", &op); if(op == 1) { scanf("%d", &d); if(a[1].sum < d) { printf("0\n"); continue; } L = Query(1, d); printf("%d\n", L); Update(1, L, L+d-1, 1);///更新从L开始的连续d个点让他们被覆盖; } else { scanf("%d %d", &L, &d); Update(1, L, L+d-1, 2);///更新从L开始的连续d个点让他们不被覆盖; } } } return 0; }