1 条题解

  • 0
    @ 2017-03-16 23:32:52

    发表域里面的第一份题解:
    此题可以用线段树做(不知道可不可以用平衡树)

    其实我看到题的第一想法是对内存分块,每一次暴力寻找合法的块。
    但是并不可行,为什么呢?因为我们只能维护块的使用,不能维护块中每一个元素的使用,这会导致如果释放已经释放过的内存,我们会算重。

    那么来看看线段树怎么做。
    线段树维护以下内容:
    size当前段所有可用内存总长度,
    sum当前段最长的一段内存长度,
    lsum当前段从左向右能延伸的最长的内存长度,
    rsum当前段从右向左能延伸的最长的内存长度,
    pos每一段内存的从右向左的能延伸的长度的开始位置。从左向右可以找到位置就是left,然而从中间断开就不行了,因此还要维护这个。

    维护的信息就这样了,那么修改就简单了。
    这里要注意一下!
    修改的时候懒标记清空一定要清为-1!!

    询问怎么办呢?
    拿到当前这么一段区间,先看左半段能否满足需求,如果可以就进入左半段递归。
    左半段不能满足,再看看中间拼起来能否满足,如果可以直接返回左边的pos。
    如果仍不能满足,看看右半段能否满足需求,如果可以就进入右半段递归。
    如果都不能,返回-1。

    此题完美解决

    #include<algorithm>
    #include<iostream>
    #include<iomanip>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    using namespace std;
    inline const int Get_Int() {
        int num=0,bj=1;
        char x=getchar();
        while(x<'0'||x>'9') {
            if(x=='-')bj=-1;
            x=getchar();
        }
        while(x>='0'&&x<='9') {
            num=num*10+x-'0';
            x=getchar();
        }
        return num*bj;
    }
    const int maxn=500005;
    struct Tree {
        int left,right,lazy;
        int size,sum,leftsum,rightsum; //size记录总共的空段 sum记录最长空段 
        int pos; //pos保存当前段如果从中间分开,左边的开始处坐标 
        Tree() {}
        Tree(int l,int r):left(l),right(r) {
            lazy=-1;
            size=sum=leftsum=rightsum=pos=0;
        }
    };
    struct Segment_Tree {
        Tree tree[maxn*4];
        #define ls (index*2) 
        #define rs (index*2+1)
        void build(int index,int Left,int Right) {
            tree[index]=Tree(Left,Right);
            if(Left==Right)return;
            int mid=(Left+Right)/2;
            build(ls,Left,mid);
            build(rs,mid+1,Right);
        }
        void push_up(int index) {
            tree[index].size=tree[ls].size+tree[rs].size;
            if(ls)tree[index].leftsum=tree[ls].leftsum;
            if(tree[ls].leftsum==tree[ls].right-tree[ls].left+1)tree[index].leftsum=max(tree[index].leftsum,tree[ls].size+tree[rs].leftsum); //左儿子内存全为空才能接右边 
            if(rs) {
                tree[index].rightsum=tree[rs].rightsum;
                tree[index].pos=tree[rs].pos;
            }
            if(tree[rs].rightsum==tree[rs].right-tree[rs].left+1) { //右儿子内存全为空才能接右边 
                tree[index].rightsum=max(tree[index].rightsum,tree[ls].rightsum+tree[rs].size);
                tree[index].pos=tree[ls].pos; //接过来后改变起始位置 
            }
            tree[index].sum=max(tree[ls].sum,max(tree[rs].sum,tree[ls].rightsum+tree[rs].leftsum));
        }
        void modify(int index,int data) {
            if(!index)return;
            tree[index].lazy=data;
            tree[index].size=tree[index].leftsum=tree[index].rightsum=tree[index].sum=data?tree[index].right-tree[index].left+1:0;
            tree[index].pos=data?tree[index].left:(tree[index].right+1);
        }
        void push_down(int index) {
            if(tree[index].lazy==-1)return;
            modify(ls,tree[index].lazy);
            modify(rs,tree[index].lazy);
            tree[index].lazy=-1;
        }
        void modify(int index,int Left,int Right,int val) {
            if(Left>tree[index].right||Right<tree[index].left)return;
            if(Left<=tree[index].left&&Right>=tree[index].right) {
                modify(index,val);
                return;
            }
            push_down(index);
            modify(ls,Left,Right,val);
            modify(rs,Left,Right,val);
            push_up(index);
        }
        int query(int index,int len) {
            if(tree[index].left==tree[index].right)return tree[index].left;
            push_down(index);
            if(tree[ls].sum>=len)return query(ls,len); //左边最长可用 访问左边
            if(tree[ls].rightsum+tree[rs].leftsum>=len)return tree[ls].pos; //左边右边拼凑可用 返回
            if(tree[rs].sum>=len)return query(rs,len); //右边最长可用 访问右边
            return -1; //没有一个可用 
        }
    } st;
    int len;
    char order; 
    int main() {
        ios::sync_with_stdio(false);
        cin>>len;
        st.build(1,1,len);
        st.modify(1,1,len,1);
        while(cin>>order) {
            if(order=='Q') {
                int x;
                cin>>x;
                if(x<=0)puts("Ivalid Request");
                else {
                    int pos=st.query(1,x);
                    if(pos!=-1)st.modify(1,pos,pos+x-1,0); //占用
                    printf("%d\n",pos); 
                }
            } else {
                int Left,Right;
                cin>>Left>>Right;
                if(Left>Right||Left<=0||Right<=0)puts("Ivalid Request");
                else {
                    st.modify(1,Left,Right,1);
                    printf("%d\n",st.tree[1].size);
                }
            }
        }
        return 0;
    }
    
  • 1

信息

难度
8
分类
数据结构 | 线段树 点击显示
标签
递交数
10
已通过
2
通过率
20%
上传者