(线段树,二分)hdoj 2871-Memory Control

Memory units are numbered from 1 up to N. 
A sequence of memory units is called a memory block. 
The memory control system we consider now has four kinds of operations: 
1.  Reset Reset all memory units free. 
2.  New x Allocate a memory block consisted of x continuous free memory units with the least start number 
3.  Free x Release the memory block which includes unit x 
4.  Get x Return the start number of the xth memory block(Note that we count the memory blocks allocated from left to right) 
Where 1<=x<=N.You are request to find out the output for M operations.

InputInput contains multiple cases. 
Each test case starts with two integer N,M(1<=N,M<=50000) ,indicating that there are N units of memory and M operations. 
Follow by M lines,each line contains one operation as describe above. 
OutputFor each “Reset” operation, output “Reset Now”. 
For each “New” operation, if it’s possible to allocate a memory block, 
output “New at A”,where Ais the least start number,otherwise output “Reject New”. 
For each “Free” operation, if it’s possible to find a memory block occupy unit x,
output “Free from A to B”,where A and B refer to the start and end number of the memory block,otherwise output “Reject Free”. 
For each “Get” operation, if it’s possible to find the xth memory blocks, 
output “Get at A”,where A is its start number,otherwise output “Reject Get”. 
Output one blank line after each test case. 
Sample Input

6 10
New 2
New 5
New 2
New 2
Free 3
Get 1
Get 2
Get 3
Free 3
Reset

Sample Output

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

区间维护依旧与Hotel题目类似。变得更加复杂的是对Free get操作时区间的维护。采用引入vector记录区间的办法,为了提高效率,每次查询、插入都需要采用二分法(利用了vector插入时是在给定地址前插入数据的特性)这种二分法的使用值得复习反思。
  1 #include <iostream>
  2 //#include<bits/stdc++.h>
  3 #include <stack>
  4 #include <queue>
  5 #include <map>
  6 #include <set>
  7 #include <cstdio>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <math.h>
 11 using namespace std;
 12 int N,M;
 13 const int MAX=5e4+5;
 14 struct node
 15 {
 16     int left,right,mid;
 17     int al,ar;
 18     int status;
 19     int len()
 20     {
 21         return ar-al+1;
 22     }
 23     void actl()
 24     {
 25         left=right=mid=(status?0:len());
 26     }
 27 }st[10*MAX];
 28 struct seg//记录区间
 29 {
 30     int left,right;
 31 };
 32 vector <seg> ve;//储存区间信息
 33 seg oh;//临时储存
 34 void init(int l,int r,int k)
 35 {
 36     st[k].al=l;
 37     st[k].ar=r;
 38     st[k].status=0;
 39     st[k].actl();
 40     if(l==r)
 41         return;
 42     init(l,(l+r)/2,2*k);
 43     init((l+r)/2+1,r,2*k+1);
 44 }
 45 void pushdown(int k)
 46 {
 47     if(st[k].status!=-1)
 48     {
 49         st[2*k].status=st[2*k+1].status=st[k].status;
 50         st[k].status=-1;
 51         st[2*k].actl();
 52         st[2*k+1].actl();
 53     }
 54 }
 55 int query(int len,int k)
 56 {
 57     if(len==1&&st[k].al==st[k].ar)
 58         return st[k].al;
 59     if(st[k].mid<len)
 60         return -1;
 61     pushdown(k);
 62     if(st[2*k].mid>=len)
 63         return query(len,2*k);
 64     else if(st[2*k].right+st[2*k+1].left>=len)
 65         return st[2*k].ar-st[2*k].right+1;
 66     else if(st[2*k+1].mid>=len)
 67         return query(len,2*k+1);
 68     return -1;
 69 }
 70 void update(int ul,int ur,int l,int r,int k,int val)
 71 {
 72     if(l==ul&&r==ur)
 73     {
 74         st[k].status=val;
 75         st[k].actl();
 76         return;
 77     }
 78     if(l==r)
 79         return;
 80     pushdown(k);
 81     int mid=(l+r)/2;
 82     if(ur<=mid)
 83         update(ul,ur,l,mid,2*k,val);
 84     else if(ul>mid)
 85         update(ul,ur,mid+1,r,2*k+1,val);
 86     else
 87     {
 88         update(ul,mid,l,mid,2*k,val);
 89         update(mid+1,ur,mid+1,r,2*k+1,val);
 90     }
 91     st[k].mid=max(st[2*k].mid,st[2*k+1].mid);
 92     st[k].left=st[2*k].left;
 93     st[k].right=st[2*k+1].right;
 94     st[k].mid=max(st[2*k].right+st[2*k+1].left,st[k].mid);
 95     if(st[2*k].left==st[2*k].len())
 96         st[k].left+=st[2*k+1].left;
 97     if(st[2*k+1].right==st[2*k+1].len())
 98         st[k].right+=st[2*k].right;
 99     return;
100 }
101 char command[10];
102 int tem,an;
103 int lo;//添加的位置
104 int binarysearch(int k)
105 {
106     int l,r,mid;
107     l=0;r=ve.size()-1;
108     while(l<=r)
109     {
110         mid=(l+r)/2;
111         if(ve[mid].left<=k)
112             l=mid+1;
113         else if(ve[mid].left>k)
114             r=mid-1;
115     }
116     return l;
117 }
118 int main()
119 {
120     while(~scanf("%d %d",&N,&M))
121     {
122         ve.clear();
123         init(1,N,1);
124         while(M--)
125         {
126             scanf("%s",command);
127             if(command[0]==‘R‘)
128             {
129                 ve.clear();
130                 st[1].status=0;
131                 st[1].actl();
132                 pushdown(1);
133                 printf("Reset Now\n");
134             }
135             else if(command[0]==‘N‘)
136             {
137                 scanf("%d",&tem);
138                 an=query(tem,1);
139                 if(an==-1)
140                     printf("Reject New\n");
141                 else
142                 {
143                     oh.left=an;oh.right=an+tem-1;
144                     lo=binarysearch(an);
145                     ve.insert(ve.begin()+lo,oh);
146
147                     update(an,an+tem-1,1,N,1,1);
148                     printf("New at %d\n",an);
149                 }
150             }
151             else if(command[0]==‘F‘)
152             {
153                 scanf("%d",&tem);
154                 lo=binarysearch(tem)-1;
155                 if(lo<=-1||ve[lo].right<tem)
156                     printf("Reject Free\n");
157                 else
158                 {
159                     update(ve[lo].left,ve[lo].right,1,N,1,0);
160                     printf("Free from %d to %d\n",ve[lo].left,ve[lo].right);
161                     ve.erase(ve.begin()+lo,ve.begin()+lo+1);//删除掉ve中的这个seg区间
162                 }
163             }
164             else if(command[0]==‘G‘)
165             {
166                 scanf("%d",&tem);
167                 if(tem>ve.size())
168                     printf("Reject Get\n");
169                 else
170                 {
171                     printf("Get at %d\n",ve[tem-1].left);
172                 }
173             }
174         }
175         printf("\n");//题意要求两组数据之间换行
176     }
177 }
 
时间: 2024-10-12 19:44:34

(线段树,二分)hdoj 2871-Memory Control的相关文章

HDU 2871 Memory Control (线段树,区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=2871 Memory Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4418    Accepted Submission(s): 1056 Problem Description Memory units are numbered

HDU 2871 Memory Control(线段树)

HDU 2871 Memory Control 题目链接 题意:内存操作,和hotel那题差不多,多一个get操作 思路:线段树区间合并,其他都差不多,多一个get操作,这个用set去乱搞就过了- -,估计数据鶸吧,多这个操作感觉要用splay去搞了 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <set> using namespace std; const i

hdu 2871 Memory Control(线段树)

题目链接:hdu 2871 Memory Control 题目大意:模拟一个内存分配机制. Reset:重置,释放所有空间 New x:申请内存为x的空间,输出左地址 Free x:释放地址x所在的内存块 Get x:查询第x个内存块,输出左地址 解题思路:一开始全用线段树去做,写的乱七八糟,其实只要用线段树维护可用内存.然后用户一个vector记录所有的内存块. #include <cstdio> #include <cstring> #include <vector>

HDU 2871 Memory Control

一共4种操作 其中用线段树 区间合并,来维护连续空的长度,和找出那个位置.其他用vector维护即可 #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #include <iostream> #include<vector> #define lson i<<1 #define rson i<<1|1 #define N

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

hdu 5592 ZYB&#39;s Premutation (线段树+二分查找)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=5592 Problem Description ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to  restore the premutation.Pair (i,j)(i<j) is considered as a reverse

Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)

题目:http://codeforces.com/contest/1156/problem/E 题意:给你1-n  n个数,然后求有多少个区间[l,r] 满足    a[l]+a[r]=max([l,r]) 思路:首先我们去枚举区间肯定不现实,我们只能取把能用的区间去用,我们可以想下每个数当最大值的时候所做的贡献 我们既然要保证这个数为区间里的最大值,我们就要从两边扩展,找到左右边界能扩展在哪里,这里你直接去枚举肯定不行 这里我们使用了线段树二分去枚举左右区间最远能走到哪里,然后很暴力的去枚举短

HDU 2871 Memory Control(线段树&#183;区间合并&#183;Vector)

题意  模拟内存申请  有n个内存单元  有以下4种操作 Reset  将n个内存单元全部清空 New x  申请一个长度为x的连续内存块  申请成功就输出左端 Free x  将x所在的内存块空间释放  释放成功输出释放的内存始末位置 Get x  输出第x个内存块的起始位置 Reset 和 New 都是基本的区间合并知识  比较简单  Free和Get需要知道内层块的位置  所以我们在New的时候要将申请的内存块的始末位置都存起来  两个内层块不会相交  这样就能通过二分找到需要的内层块了

离散化+线段树/二分查找/尺取法 HDOJ 4325 Flowers

题目传送门 题意:给出一些花开花落的时间,问某个时间花开的有几朵 分析:这题有好几种做法,正解应该是离散化坐标后用线段树成端更新和单点询问.还有排序后二分查找询问点之前总花开数和总花凋谢数,作差是当前花开的数量,放张图易理解: 还有一种做法用尺取法的思想,对暴力方法优化,对询问点排序后再扫描一遍,花开+1,花谢-1.详细看代码. 收获:一题收获很多:1. 降低复杂度可以用二分 2. 线段计数问题可以在端点标记1和-1 3. 离散化+线段树 终于会了:) (听说数据很水?) 代码1:离散化+线段树