http://acm.hdu.edu.cn/showproblem.php?pid=2871
6 10 New 2 New 5 New 2 New 2 Free 3 Get 1 Get 2 Get 3 Free 3 Reset
New at 1 Reject New New at 3 New at 5 Free from 3 to 4 Get at 1 Get at 5 Reject Get Reject Free Reset Now
题意:
Reset:清空内存
New x:申请长度为x的内存
Free x:释放x所在的内存块
Get x:询问x所在内存块的起点
分析:
New操作用线段树,找到能容纳x的最左的位置,维护节点的左/右起最长连续0的长度和对应区间内最长连续0的长度。
把现有内存块保存,用二分查找/更新即可,注意Reset时要清空。
#include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> #include<ctime> #include<cctype> #include<cmath> #include<string> #include<cstring> #include<stack> #include<queue> #include<list> #include<vector> #include<map> #include<set> #define sqr(x) ((x)*(x)) #define LL long long #define itn int #define INF 0x3f3f3f3f #define PI 3.1415926535897932384626 #define eps 1e-10 #define maxm #define maxn 200007 using namespace std; int setv[maxn<<2]; int lsum0[maxn<<2],rsum0[maxn<<2],msum0[maxn<<2]; struct Memory { int l,r; }; vector<Memory> v; inline void pushup(int k,int l,int r) { int lc=k*2+1,rc=k*2+2,m=l+r>>1; if (lsum0[lc]==m-l) lsum0[k]=lsum0[lc]+lsum0[rc]; else lsum0[k]=lsum0[lc]; if (rsum0[rc]==r-m) rsum0[k]=rsum0[rc]+rsum0[lc]; else rsum0[k]=rsum0[rc]; msum0[k]=max(rsum0[lc]+lsum0[rc],max(msum0[lc],msum0[rc])); } inline void pushdown(int k,int l,int r) { if (setv[k]!=-1) { int lc=k*2+1,rc=k*2+2,m=l+r>>1; setv[lc]=setv[rc]=setv[k]; lsum0[lc]=rsum0[lc]=msum0[lc]=setv[k]?0:m-l; lsum0[rc]=rsum0[rc]=msum0[rc]=setv[k]?0:r-m; setv[k]=-1; } } void update(int a,int b,int v,int k,int l,int r) { if (b<=l || r<=a) return ; if (a<=l && r<=b) { setv[k]=v; lsum0[k]=rsum0[k]=msum0[k]=v?0:r-l; } else { pushdown(k,l,r); update(a,b,v,k*2+1,l,l+r>>1); update(a,b,v,k*2+2,l+r>>1,r); pushup(k,l,r); } } int query(int w,int k,int l,int r) { int lc=k*2+1,rc=k*2+2,m=l+r>>1; if (r-l==1) return l; if (r-l!=1) pushdown(k,l,r); if (msum0[lc]>=w) return query(w,lc,l,m); if (rsum0[lc]+lsum0[rc]>=w) return m-rsum0[lc]; return query(w,rc,m,r); } int bin_search(int k) { int l=0,r=v.size()-1,ans=-1; while (l<=r) { itn mid=l+r>>1; if (v[mid].l<=k) { l=mid+1; ans=mid; } else { r=mid-1; } } return ans; } int main() { #ifndef ONLINE_JUDGE freopen("/home/fcbruce/文档/code/t","r",stdin); #endif // ONLINE_JUDGE int n,m,w,a,b,p; char op[10]; while (~scanf("%d %d",&n,&m)) { v.clear(); update(0,n,0,0,0,n); while (m--) { scanf("%s",op); if (op[0]=='R') { v.clear(); puts("Reset Now"); update(0,n,0,0,0,n); continue; } if (op[0]=='N') { scanf("%d",&w); if (w<=msum0[0]) { a=query(w,0,0,n); b=a+w; update(a,b,1,0,0,n); printf("New at %d\n",a+1); Memory temp; temp.l=a+1; temp.r=b; int id=bin_search(a+1)+1; v.insert(v.begin()+id,temp); } else puts("Reject New"); continue; } if (op[0]=='F') { scanf("%d",&p); int id=bin_search(p); if (id==-1 || v[id].r<p) puts("Reject Free"); else { printf("Free from %d to %d\n",v[id].l,v[id].r); update(v[id].l-1,v[id].r,0,0,0,n); v.erase(v.begin()+id,v.begin()+id+1); } continue; } if (op[0]=='G') { scanf("%d",&w); if (w<=v.size()) printf("Get at %d\n",v[w-1].l); else puts("Reject Get"); } } puts(""); } return 0; }
HDU 2871 Memory Control (线段树,区间合并)
原文地址:http://blog.csdn.net/u012965890/article/details/38031827