hdu 2871 Memory Control (区间合并 连续段的起始位置 点所属段的左右端点)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871
题意:
四种操作:
1.Reset 清空所有内存
2.New x 分配一个大小为x的内存块返回,返回能分配的最小的起始点
3.Free x 释放当前点所在的内存块,并输出左右端点
4.Get x 返回第x个内存块的起始点
讨论每个操作的写法:
第一个操作,把线段树初始化就好了
第二个操作,区间合并的基础操作,
第三个操作:多维护两个数组:st,ed代表当前点所属内存块的左右区间
第四个操作:再开棵树,存每个内存块的起始点,每个起始点下标+1,然后直接找第k大就好了。注意每次2,3,操作内存块发生变化时记得更新这个树上的信息。
题面说了每组数据中间要有空行,不然会PE.
实现代码:
#include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 #define ls rt<<1 #define rs rt<<1|1 const int M = 1e5 + 10; int lsum[M<<2],rsum[M<<2],sum[M<<2],lazy[M<<2],st[M<<2],ed[M<<2]; int cnt[M<<2],cov[M<<2],n; void pushup(int l,int r,int rt){ mid; lsum[rt] = lsum[ls]; rsum[rt] = rsum[rs]; sum[rt] = max(sum[ls],sum[rs]); if(lsum[rt] == m-l+1) lsum[rt] += lsum[rs]; if(rsum[rt] == r-m) rsum[rt] += rsum[ls]; sum[rt] = max(rsum[ls]+lsum[rs],sum[rt]); } void pushdown(int l,int r,int rt){ if(lazy[rt]!=-1){ mid; lazy[ls] = lazy[rs] = lazy[rt]; sum[ls] = lsum[ls] = rsum[ls] = (m-l+1)*lazy[rt]; sum[rs] = lsum[rs] = rsum[rs] = (r-m)*lazy[rt]; st[ls] = st[rs] = st[rt]; ed[ls] = ed[rs] = ed[rt]; lazy[rt] = -1; } } void update(int L,int R,int c,int l,int r,int rt){ if(L <= l&&R >= r){ lazy[rt] = c; lsum[rt] = rsum[rt] = sum[rt] = (r-l+1)*c; if(c) st[rt] = ed[rt] = -1; else{ st[rt] = L; ed[rt] = R; } return ; } pushdown(l,r,rt); mid; if(L <= m) update(L,R,c,lson); if(R > m) update(L,R,c,rson); pushup(l,r,rt); } void rebuild(){ update(1,n,1,1,n,1); //cout<<sum[1]<<endl; cnt[1] = 0; cov[1] = 1; } int New(int p,int l,int r,int rt){ //返回空位的左边界 if(l == r) return l; mid; pushdown(l,r,rt); if(sum[ls] >= p) return New(p,lson); else if(rsum[ls]+lsum[rs]>=p) return m-rsum[ls]+1; else return New(p,rson); } int Free(int p,int l,int r,int rt){ if(l == r) return rt; mid; pushdown(l,r,rt); if(p <= m) return Free(p,lson); else return Free(p,rson); } void up(int rt){ cnt[rt] = cnt[ls] + cnt[rs]; } void down(int rt){ if(cov[rt]){ cnt[ls] = cnt[rs] = 0; cov[ls] = cov[rs] = 1; cov[rt] = 0; } } int get(int p,int l,int r,int rt){ if(l == r) return l; mid; down(rt); if(cnt[ls] >= p) return get(p,lson); else return get(p-cnt[ls],rson); } void change(int p,int c,int l,int r,int rt){ if(l == r){ cnt[rt] = c; return; } down(rt); mid; if(p <= m) change(p,c,lson); else change(p,c,rson); up(rt); } int main() { int q,k,x; while(scanf("%d%d",&n,&q)!=EOF){ rebuild(); while(q--){ char op[20]; scanf("%s",op); if(op[0] == 'N'){ scanf("%d",&x); //cout<<sum[1]<<" "<<x<<endl; if(sum[1] < x) printf("Reject New\n"); else{ int k = New(x,1,n,1); printf("New at %d\n",k); change(k,1,1,n,1); update(k,k+x-1,0,1,n,1); } } else if(op[0]=='F'){ scanf("%d",&x); int k = Free(x,1,n,1); if(st[k] < 0) printf("Reject Free\n"); else{ printf("Free from %d to %d\n",st[k],ed[k]); change(st[k],0,1,n,1); update(st[k],ed[k],1,1,n,1); } } else if(op[0] == 'R'){ rebuild(); printf("Reset Now\n"); } else{ scanf("%d",&x); if(x > cnt[1]) printf("Reject Get\n"); else printf("Get at %d\n",get(x,1,n,1)); } } printf("\n"); } return 0; }