题目大意:Hotel有N(1 ≤ N ≤ 50,000)间rooms,并且所有的rooms都是连续排列在同一边,groups需要check in 房间,要求房间的编号为连续的r..r+Di-1并且r是最小的;visitors同样可能check
out,并且他们每次check out都是编号为Xi ..Xi +Di-1
(1 ≤ Xi ≤ N-Di+1)的房间,题目的输入有两种样式:
- 1 a : groups需要check in a间编号连续的房间,然后这些房间住进去
- 2 a b : visitors check out 房间,其中房间编号是 a…a+b-1,这些房间清空
要求对于每次request,输出为groups分配数目为a的房间中编号最小的房间编号
维护几个数据:该区间最大连续长度,从左边第一个开始的最大连续长度lmax,从右边开始的最大连续长度rmax,是否颜色一样(是某个颜色)tong;
然后a[root*2].rmax+a[root*2+1].lmax就是中间部分的长度,一些细节比较难以处理,要注意一下。
这题和POJ3368真的太像了,简直是孪生兄弟。
本题的重点是如何处理中间接起来的问题,当然3368也是。
具体就看代码吧:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<math.h> #include<stdlib.h> using namespace std; struct pai { int left, right, lmax, rmax, zmax, tong,col; }a[50000*4+20]; struct PP { int left; int right; }o; void up(int root) { int tmax; if (a[root * 2].tong==1 && a[root * 2 + 1].tong==1)//说明房间还有,这里很可能有问题,脑子乱 { a[root].tong = 1; } a[root].rmax = a[root * 2 + 1].rmax; a[root].lmax = a[root * 2].lmax; if (a[root * 2].rmax && a[root * 2 + 1].lmax) { if (a[root * 2 + 1].tong==1) { tmax = a[root * 2 + 1].zmax + a[root * 2].rmax; a[root].rmax = tmax; } if (a[root * 2].tong==1) { tmax = a[root * 2].zmax + a[root * 2 + 1].lmax; a[root].lmax = tmax; } tmax = a[root * 2].rmax + a[root * 2 + 1].lmax; } else { tmax = -1; } int max1 = a[root * 2].zmax; int max2 = a[root * 2 + 1].zmax; int max3 = max(max1, max2); max3 = max(tmax, max3); a[root].zmax = max3; } void down(int root) { if (a[root].tong == 0) { a[root * 2].lmax =a[root*2].rmax=a[root*2].zmax= 0; a[root * 2+1].lmax = a[root * 2+1].rmax = a[root * 2+1].zmax = 0; a[root * 2].tong = a[root * 2 + 1].tong = 0; a[root].tong = 7; } if (a[root].tong == 1) { a[root * 2].lmax = a[root * 2].rmax = a[root * 2].zmax = a[root * 2].right - a[root * 2].left + 1; a[root * 2 + 1].lmax = a[root * 2 + 1].rmax = a[root * 2 + 1].zmax = a[root * 2+1].right - a[root * 2+1].left + 1; a[root * 2].tong = a[root * 2 + 1].tong = 1; a[root].tong = 7; } } void build(int left, int right, int root) { a[root].left = left; a[root].right = right; if (left == right) { a[root].lmax = 1; a[root].rmax = 1; a[root].lmax = 1; a[root].zmax = 1; a[root].tong = 1; a[root].col = 1; return; } int m = (left + right) / 2; build(left, m, root * 2); build(m + 1, right, root * 2 + 1); up(root); } int search(int left, int right, int root,int x) { if (a[root].zmax < x) { return -1; } if (a[root * 2].lmax >= x) { o.left = a[root * 2].left; o.right = a[root * 2].left + x - 1; return o.left; } if (a[root * 2].zmax >= x) { return search(a[root * 2].left, a[root * 2].right, root * 2, x); } if ((a[root * 2].rmax + a[root * 2 + 1].lmax) >= x) { o.left = a[root * 2].right - a[root * 2].rmax + 1;//这里有可能不对 o.right = o.left + x - 1; return o.left; } return search(a[root * 2 + 1].left, a[root * 2 + 1].right, root * 2 + 1, x); } void change(int left, int right, int root, int x) { if (a[root].left >= left && a[root].right <= right) { a[root].lmax = a[root].rmax = a[root].zmax=a[root].tong = 0;//tong先没搞 return; } down(root); int m = (a[root].left + a[root].right) / 2; if (left <= m) { change(left, right, root * 2, x); } if (right > m) { change(left,right, root * 2+1, x); } up(root); } void change2(int left, int right, int root, int x) { if (a[root].left >= left && a[root].right <= right) { a[root].lmax = a[root].rmax = a[root].zmax=a[root].right-a[root].left+1; a[root].tong = 1; return; } down(root); int m = (a[root].left + a[root].right) / 2; if (left <= m) { change2(left, right, root * 2, x); } if (right > m) { change2(left, right, root * 2 + 1, x); } up(root); } int main() { int i,j,n, m,temp,b,c,temp2; while (~scanf("%d%d", &n, &m)) { build(1, n, 1); for (i = 0; i < m; i++) { scanf("%d", &temp); if (temp == 1) { scanf("%d", &b); temp2=search(1, n, 1, b); if (temp2 != -1) { cout << temp2 << endl; } else { cout << '0' << endl; continue; } change(o.left, o.right, 1, 0); } else { scanf("%d%d", &b, &c); change2(b,b+c-1, 1, 1); } } } }
时间: 2024-10-13 01:13:58