HDU 2871 Memory Control (线段树神题)

来源:互联网 发布:linux下路由跟踪命令 编辑:程序博客网 时间:2024/06/05 18:09

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

初状态全为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|1using 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
原创粉丝点击