HDU 2871 Memory Control (线段树神题)

神题。。综合了线段树的所有操作,很锻炼代码能力。

初状态全为0

ls,ms,rs记录区间连续的0,lv,rv记录其所属block的左右端点,c为其懒标记,

cnt记录区间的block数,clr记录是否重置。


代码:

#include<iostream>
#include<cstdio>
#include<algorithm>

#define lson l , m , rt<<1
#define rson m+1,r , rt<<1|1
using namespace std;
typedef long long LL;
const int maxn = 80005;

struct SegTree{
    int ls[maxn<<2],ms[maxn<<2],rs[maxn<<2],c[maxn<<2];
    int cnt[maxn<<2],clr[maxn<<2];
    int lv[maxn<<2],rv[maxn<<2];
    void push_up(int l,int r,int rt){
        int m = (l + r) >> 1;
        ms[rt] = max(max(ms[rt<<1],ms[rt<<1|1]),rs[rt<<1]+ls[rt<<1|1]);
        ls[rt] = ls[rt<<1] == m-l+1 ? ls[rt<<1]+ls[rt<<1|1] : ls[rt<<1];
        rs[rt] = rs[rt<<1|1] == r-m ? rs[rt<<1|1]+rs[rt<<1] : rs[rt<<1|1];
    }
    void push_down(int l,int r,int rt){
        if(c[rt] == -1) return;
        int m = (l + r) >> 1;
        c[rt<<1] = c[rt<<1|1] = c[rt];
        if(c[rt]) ms[rt<<1] = ls[rt<<1] = rs[rt<<1] =
            ms[rt<<1|1] = ls[rt<<1|1] = rs[rt<<1|1] = 0;
        else{
            ms[rt<<1] = ls[rt<<1] = rs[rt<<1] = m-l+1;
            ms[rt<<1|1] = ls[rt<<1|1] = rs[rt<<1|1] = r-m;
        }
        lv[rt<<1] = lv[rt<<1|1] = lv[rt];
        rv[rt<<1] = rv[rt<<1|1] = rv[rt];
        c[rt] = -1;
    }
    void cnt_up(int rt){
        cnt[rt] = cnt[rt<<1] + cnt[rt<<1|1];
    }
    void clear(int l,int r,int rt){
        if(clr[rt] == 0) return;
        clr[rt<<1] = clr[rt<<1|1] = clr[rt];
        cnt[rt<<1] = cnt[rt<<1|1] = clr[rt] = 0;
    }
    void build(int l,int r,int rt){
        c[rt] = lv[rt] = rv[rt] = -1;clr[rt] = cnt[rt] = 0;
        if(l == r){
            ls[rt] = ms[rt] = rs[rt] = 1;
            return;
        }
        int m = (l + r) >> 1;
        build(lson);build(rson);
        push_up(l,r,rt);
    }
    int New(int x,int l,int r,int rt){
        if(ms[rt] < x) return -1;
        if(l == r) return l;
        push_down(l,r,rt);
        int m = (l + r) >> 1;
        if(ms[rt<<1] >= x) return New(x,lson);
        else if(rs[rt<<1]+ls[rt<<1|1] >= x) return m-rs[rt<<1]+1;
        else return New(x,rson);
    }
    int Free(int x,int l,int r,int rt){
        if(l == r) return rt;
        push_down(l,r,rt);
        int m = (l + r) >> 1;
        if(m >= x) return Free(x,lson);
        else return Free(x,rson);
    }
    int Get(int x,int l,int r,int rt){
        if(cnt[rt] < x) return -1;
        if(l == r) return l;
        clear(l,r,rt);
        int m = (l + r) >> 1;
        if(cnt[rt<<1] >= x) return Get(x,lson);
        else return Get(x-cnt[rt<<1],rson);
    }
    void MemFill(int a,int b,int x,int l,int r,int rt){
        if(l > b || r < a) return;
        if(a <= l && r <= b){
            ms[rt] = ls[rt] = rs[rt] = x ? 0 : r-l+1;
            lv[rt] = x ? a : -1;
            rv[rt] = x ? b : -1;
            c[rt] = x;
            return;
        }
        push_down(l,r,rt);
        int m = (l + r) >> 1;
        MemFill(a,b,x,lson);MemFill(a,b,x,rson);
        push_up(l,r,rt);
    }
    void update(int k,int x,int l,int r,int rt){
        if(l == r){
            cnt[rt] = x;
            return;
        }
        clear(l,r,rt);
        int m = (l + r) >> 1;
        if(m >= k) update(k,x,lson);
        else update(k,x,rson);
        cnt_up(rt);
    }
}sol;

int main(){
    int n,q,x;char ch[10];
    while(~scanf("%d%d",&n,&q)){
        sol.build(1,n,1);
        while(q--){
            scanf("%s",ch);
            if(ch[0] == 'R'){
                sol.cnt[1] = 0;
                sol.clr[1] = 1;
                sol.MemFill(1,n,0,1,n,1);
                printf("Reset Now\n");
            }else{
                scanf("%d",&x);
                if(ch[0] == 'N'){
                    int pos = sol.New(x,1,n,1);
                    if(pos == -1) printf("Reject New\n");
                    else{
                        sol.MemFill(pos,pos+x-1,1,1,n,1);
                        sol.update(pos,1,1,n,1);
                        printf("New at %d\n",pos);
                    }
                }else if(ch[0] == 'F'){
                    int pos = sol.Free(x,1,n,1);
                    if(sol.lv[pos] < 0) printf("Reject Free\n");
                    else{
                        printf("Free from %d to %d\n",sol.lv[pos],sol.rv[pos]);
                        sol.update(sol.lv[pos],0,1,n,1);
                        sol.MemFill(sol.lv[pos],sol.rv[pos],0,1,n,1);
                    }
                }else{
                    int pos = sol.Get(x,1,n,1);
                    if(pos == -1) printf("Reject Get\n");
                    else printf("Get at %d\n",pos);
                }
            }
        }
        putchar('\n');
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值