• hdu 2871 Memory Control


    线段树

    题意:1到n的线段,m个操作

    Reset 将所有内存清空

    New x 申请一段长度为x的最左的未被占用的区间,返回它的位置,并占用它。找不到输出Reject New

    Free x 找到x单元内存所在的连续的单元块,返回这个单元块的左右端点,并且清空这个单元块,如果这个单元x根本没被占用,则输出Reject Free

    Get x 找到第x个单元块(而不是第x单元),返回这个单元块的起始位置即左端点

    这题还是和 poj 3667 Hotel 是一样的,查询一个最左的合法区间,修改一段区间

    这题使用vector按顺序来保存单元块,方便查找(可以使用二分)

    而线段树主要的query和updata函数是一样的

    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    #define lch(i) ((i)<<1)
    #define rch(i) ((i)<<1|1)
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define N 50010
    
    struct block{
        int l,r;
    };
    struct node{
        int l,r;
        int mark;
        int tlen,llen,rlen;
        int mid(){
            return (l+r)>>1;
        }
        int cal_len(){
            return r-l+1;
        }
        void updata_len(){
            tlen=llen=rlen= (mark ? 0 : cal_len());
        }
    };
    typedef struct block Block;
    typedef struct node node;
    vector <Block> B;
    node t[4*N];
    
    void build(int l ,int r ,int rt)
    {
        t[rt].l = l; t[rt].r = r; 
        t[rt].mark = 0;
        t[rt].updata_len();
        if(l == r) return ;
        int mid = t[rt].mid();
        int ll = lch(rt);
        int rr = rch(rt);
        build(l , mid , ll);
        build(mid+1 , r , rr);
        return ;
    }
    
    void updata(int l , int r , int val , int rt)
    {
        if(t[rt].l == l && t[rt].r == r) 
        {
            t[rt].mark = val;
            t[rt].updata_len();
            return ;
        }
        int mid = t[rt].mid();
        int ll = lch(rt);
        int rr = rch(rt);
        
        if(t[rt].mark != -1)
        {
            t[ll].mark = t[rr].mark = t[rt].mark;
            t[rt].mark = -1;
            t[ll].updata_len();
            t[rr].updata_len();
        }
    
        if(l > mid)        updata(l , r , val , rr);
        else if(r <= mid)  updata(l , r , val , ll);
        else
        {
            updata(l , mid , val , ll);
            updata(mid+1 , r , val , rr);
        }
    
        t[rt].tlen = max( max(t[ll].tlen , t[rr].tlen)  ,  t[ll].rlen+t[rr].llen);
        t[rt].llen = t[ll].llen;  t[rt].rlen = t[rr].rlen;
        if(t[ll].tlen == t[ll].cal_len()) t[rt].llen += t[rr].llen;
        if(t[rr].tlen == t[rr].cal_len()) t[rt].rlen += t[ll].rlen;
        return ;
    }
    
    int query(int w , int rt)
    {
        if(t[rt].l == t[rt].r)
        {
            if(w == 1) return t[rt].l;
            else       return 0;
        }
    
        int mid = t[rt].mid();
        int ll = lch(rt);
        int rr = rch(rt);
        
        if(t[rt].mark != -1)
        {
            t[ll].mark = t[rr].mark = t[rt].mark;
            t[rt].mark = -1;
            t[ll].updata_len();
            t[rr].updata_len();
        }
    
        if(t[ll].tlen >= w) 
            return query(w , ll);
        else if(t[ll].rlen + t[rr].llen >= w)
            return t[ll].r - t[ll].rlen + 1;
        else if(t[rr].tlen >= w)
            return query(w , rr);
        else
            return 0;
    }
    
    int binarysearch(int key)
    {
        int low = 0;
        int high = B.size() - 1;
        while(low <= high)
        {
            int mid = (low + high) >> 1;
            if(B[mid].l <= key)
                low = mid + 1;
            else
                high = mid - 1;
        }
        return low;
        //此二分查找最终返回low,二分查找要写好,否则很难查错
        //B[low]代表的块是大于pos的,B[low-1]小于pos
        //对于添加一个新的区间,是在low这里添加,原来的low以及后面的区间往后移动
        //对于删除一个区间,是low-1,low以及后面的区间往前移动
    }
    
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            B.clear();
            build(1,n,1);
            while(m--)
            {
                char op[10];
                int x,pos,index;
                Block tmp;
                scanf("%s",op);
                if(!strcmp(op,"Reset"))
                {
                    updata(1,n,0,1);
                    B.clear();
                    puts("Reset Now");
                    continue;
                }
    
                scanf("%d",&x);
                if(!strcmp(op,"New"))
                {
                    pos = query(x,1);
                    if(!pos) 
                    {
                        puts("Reject New");
                        continue;
                    }
                    printf("New at %d\n",pos);
                    tmp.l = pos;  tmp.r = pos + x -1;
                    index = binarysearch(pos);
                    B.insert(B.begin()+index , tmp);
                    updata(tmp.l , tmp.r , 1 , 1);
                }
                else if(!strcmp(op,"Free"))
                {
                    index = binarysearch(x) - 1;
                    if(index == -1 || B[index].r < x)
                    {
                        puts("Reject Free");
                        continue;
                    }
                    printf("Free from %d to %d\n",B[index].l , B[index].r);
                    updata(B[index].l , B[index].r , 0 , 1);
                    B.erase(B.begin()+index , B.begin()+index+1);
                }
                else  //Get
                {
                    if(--x >= B.size()) 
                    {
                        puts("Reject Get");
                        continue;
                    }
                    printf("Get at %d\n",B[x].l);
                }
            }
            printf("\n");
        }
        return 0;
    }
  • 相关阅读:
    bzoj3676 [Apio2014]回文串
    bzoj4199 [Noi2015]品酒大会
    bzoj3171 [Tjoi2013]循环格
    bzoj4709 [Jsoi2011]柠檬
    bzoj2668 [cqoi2012]交换棋子
    bzoj1458 士兵占领
    25号搜索的一些例子,。。Oil Deposits&&Red and Black&&Knight Moves&&Catch That Cow&&Tempter of the Bone
    第一次超水(我错了,有难度的)的组队赛!!!The Coco-Cola Store &&Multiple of 17&& Box Game
    博弈 7月24号:HDU 2176(Nim博弈)
    2013年7月23号:大数的加与乘I-number&&Power of Cryptography
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3066405.html
Copyright © 2020-2023  润新知