hdu2871_Memory Control

来源:互联网 发布:广州淘宝实景摄影棚 编辑:程序博客网 时间:2024/05/08 11:03

http://acm.hdu.edu.cn/showproblem.php?pid=2871


由于做过hotel(poj3667),所以连数据规模都不用看就知道这题是线段树。

hotel的check-in对应此题的new,check-out对应free,build对应reset(一开始是打算用build来实现reset,后来注意到,直接用update把1到n全都设置为空即可,利用lazy update,否则重新build会tle)。

当然,由于Free操作跟hotel里的还不是完全一样,而且也多了个Get操作,本来还想修改query,后来发现,只需要维护多一个数组,按顺序记录每一个使用中的数据块的起始和结束位置即可。由于vector的插入和删除非常方便,所以就使用vector了~


特别注意:

1、在vector里查找某个unit在哪个block的时候,要用二分查找。。。TAT 我就是TLE死在这里。。。懂得把New的改为二分查找,居然忘了修改Free里面的,结果还是没拿到first blood,这道题到练习赛结束还是没人过。。

2、在Free操作里,二分查找使用upper_bound而不用lower_bound,因为如果遇到要Free的那个block刚好begin就是unit x,那么lower_bound的结果是那个block,而不是那个block的下一个位置,不需要再减1。


代码:

#include <cstdio>#include <algorithm>#include <vector>using namespace std;const int N = 50000 + 10;struct SegTree{int left, right;int maxval, lval, rval;int cover;int mid(){return (left + right) / 2;}int dis(){return right - left + 1;}void init(){maxval = lval = rval = cover ? 0 : dis();}}st[N*4];struct block{    int begin, end;};vector<block> v;bool cmp(const block &a, const block &b){    return a.begin < b.begin;}void build(int left, int right, int root){st[root].left = left;st[root].right = right;st[root].cover = 0;st[root].init();if (left == right)return;int mid = st[root].mid();build(left, mid, root*2);build(mid+1, right, root*2+1);}void update(int left, int right, int cov, int root){if (left <= st[root].left && st[root].right <= right){st[root].cover = cov;st[root].init();return;}if (st[root].cover != -1){st[root*2].cover = st[root*2+1].cover = st[root].cover;st[root*2].init();st[root*2+1].init();st[root].cover = -1;}int mid = st[root].mid();if (left <= mid)update(left, right, cov, root*2);if (right > mid)update(left, right, cov, root*2+1);st[root].maxval = max(st[root*2].rval + st[root*2+1].lval, max(st[root*2].maxval, st[root*2+1].maxval));st[root].lval = st[root*2].lval;st[root].rval = st[root*2+1].rval;if (st[root*2].lval == st[root*2].dis())st[root].lval += st[root*2+1].lval;if (st[root*2+1].rval == st[root*2+1].dis())st[root].rval += st[root*2].rval;}int query(int d, int root){if (st[root].maxval < d)return 0;if (st[root].left == st[root].right)return st[root].left;if (st[root].cover != -1){st[root*2].cover = st[root*2+1].cover = st[root].cover;st[root*2].init();st[root*2+1].init();st[root].cover = -1;}if (st[root*2].maxval >= d)return query(d, root*2);else if (st[root*2].rval + st[root*2+1].lval >= d)return st[root*2].right - st[root*2].rval + 1;else return query(d, root*2+1);}int main(){int n, m;while (scanf("%d%d", &n, &m) != EOF)    {        build(1, n, 1);        v.clear();        int x;        char s[6], ch;        while (m--)        {            scanf("%c", &ch);  //read '\n' in the end of last line            scanf("%s", s);            if (s[0] == 'R')            {//              build(1, n, 1);    //TLE!!!                update(1, n, 0, 1);                v.clear();                printf("Reset Now\n");            }            else if (s[0] == 'N')            {                scanf("%d", &x);                int a = query(x, 1);                if (a == 0)                    printf("Reject New\n");                else                {                    printf("New at %d\n", a);                    update(a, a + x - 1, 1, 1);                    //update v[]                    block y;                    y.begin = a, y.end = a + x - 1;                    vector<block>::iterator it;                    it = upper_bound(v.begin(), v.end(), y, cmp); //lower_bound() is all right.                    v.insert(it, y);//                  v.push_back(y);           //TLE!!!//                  sort(v.begin(), v.end(), cmp);                }            }            else if (s[0] == 'F')            {                scanf("%d", &x);                //find which block the x located                block y;                y.begin = x, y.end = x;                vector<block>::iterator it;                it = upper_bound(v.begin(), v.end(), y, cmp);  //lower_bound() may make the code uglier.                int tmp = it - v.begin() - 1;                if (tmp == - 1 || v[tmp].end < x)                    printf("Reject Free\n");                else                {                    printf("Free from %d to %d\n", v[tmp].begin, v[tmp].end);                    update(v[tmp].begin, v[tmp].end, 0, 1);                    v.erase(v.begin() + tmp);                }            }            else            {                scanf("%d", &x);                if (x > v.size())                    printf("Reject Get\n");                else printf("Get at %d\n", v[x-1].begin);            }        }        printf("\n");    }return 0;}