• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LyonLys
愿意在角落唱沙哑的歌 再大声也都是给你 请用心听 不要说话 Contact me via E-mail: lyon.lys@gmail.com
博客园    首页    新随笔    联系   管理    订阅  订阅

hdu 2871 Memory Control

http://acm.hdu.edu.cn/showproblem.php?pid=2871

  这是要用线段树的一道模拟题,题意相当简单,就是模拟内存分配的操作。题目用到线段树【单点更新,单点查询,区间更新,查找区间】的功能。

  New:寻找是否有大于指定长度的区间,并将区间染色,标记起始位置。

  Free:查询单点值,如果已被占用,则删除该区间。

  Get:查找第x个区间,并返回起始位置。

  Reset:将区间清空。

 

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <vector>
  4 #include <algorithm>
  5 #include <cassert>
  6 
  7 using namespace std;
  8 
  9 #define lson l, m, rt << 1
 10 #define rson m + 1, r, rt << 1 | 1
 11 
 12 typedef vector<int> vi;
 13 const int maxn = 50005;
 14 
 15 vi start, end;
 16 int cnt[maxn << 2], mark[maxn << 2], late[maxn << 2], left[maxn << 2], right[maxn << 2], mx[maxn << 2];
 17 
 18 /*****以下是统计端点位置与个数的线段树*****/
 19 void build(int l, int r, int rt){
 20     cnt[rt] = 0;
 21     if (l == r){
 22         return ;
 23     }
 24     int m = (l + r) >> 1;
 25 
 26     build(lson);
 27     build(rson);
 28 }
 29 
 30 void up1(int rt){
 31     cnt[rt] = cnt[rt << 1] + cnt[rt << 1 | 1];
 32 }
 33 
 34 void add1(int key, int p, int l, int r, int rt){
 35     if (l == r){
 36         //assert(l == p);
 37         cnt[rt] += key;
 38         return ;
 39     }
 40     int m = (l + r) >> 1;
 41 
 42     if (p <= m) add1(key, p, lson);
 43     else add1(key, p, rson);
 44     up1(rt);
 45 }
 46 
 47 int find1(int k, int l, int r, int rt){
 48     if (l == r){
 49         return l;
 50     }
 51     int m = (l + r) >> 1;
 52 
 53     //printf("%d %d %d   cnt %d\n", k, l, r, cnt[rt << 1]);
 54     if (cnt[rt << 1] >= k) return find1(k, lson);
 55     else return find1(k - cnt[rt << 1], rson);
 56 }
 57 /******************************************/
 58 
 59 
 60 /*******以下是标记区间占用情况的线段树*******/
 61 void up2(int rt, int len){
 62     int l = rt << 1;
 63     int r = rt << 1 | 1;
 64 
 65     mx[rt] = max(max(mx[l], mx[r]), left[r] + right[l]);
 66     if (left[l] == len - (len >> 1)) left[rt] = left[l] + left[r];
 67     else left[rt] = left[l];
 68     if (right[r] == (len >> 1)) right[rt] = right[r] + right[l];
 69     else right[rt] = right[r];
 70 }
 71 
 72 void down2(int rt, int len){
 73     if (late[rt] != -2){
 74         int l = rt << 1;
 75         int r = rt << 1 | 1;
 76 
 77         mark[l] = late[l] = late[rt];
 78         mark[r] = late[r] = late[rt];
 79         if (~late[rt]){
 80             mx[l] = left[l] = right[l] = 0;
 81             mx[r] = left[r] = right[r] = 0;
 82         }
 83         else{
 84             int m = len >> 1;
 85 
 86             mx[l] = left[l] = right[l] = len - m;
 87             mx[r] = left[r] = right[r] = m;
 88         }
 89         late[rt] = -2;
 90     }
 91 }
 92 
 93 void update2(int k, int L, int R, int l, int r, int rt){
 94     if (L <= l && r <= R){
 95         late[rt] = mark[rt] = k;
 96         if (~k){
 97             mx[rt] = left[rt] = right[rt] = 0;
 98         }
 99         else{
100             mx[rt] = left[rt] = right[rt] = r - l + 1;
101         }
102         return ;
103     }
104     int m = (l + r) >> 1;
105 
106     down2(rt, r - l + 1);
107     if (L <= m) update2(k, L, R, lson);
108     if (m < R) update2(k, L, R, rson);
109     up2(rt, r - l + 1);
110     //printf("%d %d %d %d %d\n", l, r, rt, mx[rt], mx[5]);
111 }
112 
113 int find2(int len, int l, int r, int rt){
114     int m = (l + r) >> 1;
115     int tl = rt << 1, tr = rt << 1 | 1;
116 
117     down2(rt, r - l + 1);
118     if (len == r - l + 1) return l;
119     if (mx[tl] >= len){
120         return find2(len, lson);
121     }
122     else if (right[tl] + left[tr] >= len){
123         return m - right[tl] + 1;
124     }
125     else{
126         return find2(len, rson);
127     }
128 }
129 
130 int query(int x, int l, int r, int rt){
131     if (l == r){
132         //assert(x == l);
133         return mark[rt];
134     }
135     int m = (l + r) >> 1;
136 
137     down2(rt, r - l + 1);
138     if (x <= m) return query(x, lson);
139     else return query(x, rson);
140 }
141 /******************************************/
142 
143 void deal(int n, int m){
144     char buf[10];
145     int k;
146 
147     start.clear();
148     end.clear();
149 
150     update2(-1, 1, n, 1, n, 1);
151     build(1, n, 1);
152     //puts("Built!");
153     while (m--){
154         scanf("%s", buf);
155         if (!strcmp(buf, "Reset")){
156             update2(-1, 1, n, 1, n, 1); // 重置区间
157             while (cnt[1]){
158                 int t = find1(1, 1, n, 1);
159                 add1(-1, t, 1, n, 1); //清空计数器
160             }
161             puts("Reset Now");
162         }
163         else if (!strcmp(buf, "New")){
164             scanf("%d", &k);
165             if (mx[1] < k){
166                 puts("Reject New");
167                 continue;
168             }
169 
170             int s = find2(k, 1, n, 1); // 查找满足要求的区间的起点
171             int t = start.size();
172 
173             add1(1, s, 1, n, 1); // 起点位置的计数器加一
174             //printf("ss %d %d\n", s, s + k - 1);
175             update2(t, s, s + k - 1, 1, n, 1); //更新区间
176             //printf("mx  %d\n", mx[1]);
177             start.push_back(s);
178             end.push_back(s + k - 1);
179             printf("New at %d\n", s);
180         }
181         else if (!strcmp(buf, "Free")){
182             scanf("%d", &k);
183 
184             int t = query(k, 1, n, 1); // 找到位置所属区间的标号
185             //printf("tt %d\n", t);
186             if (~t){
187                 //printf("s %d t %d\n", start[t], end[t]);
188                 update2(-1, start[t], end[t], 1, n, 1); // 删除区间
189                 add1(-1, start[t], 1, n, 1); // 起始位置的计数器减一
190                 printf("Free from %d to %d\n", start[t], end[t]);
191             }
192             else{
193                 puts("Reject Free");
194             }
195         }
196         else if (!strcmp(buf, "Get")){
197             scanf("%d", &k);
198             if (cnt[1] < k){
199                 puts("Reject Get");
200                 continue;
201             }
202 
203             printf("Get at %d\n", find1(k, 1, n, 1)); // 返回第k个区间的位置
204         }
205     }
206     puts("");
207 }
208 
209 int main(){
210     int n, m;
211 
212     //freopen("in", "r", stdin);
213 
214     while (~scanf("%d%d", &n, &m)){
215         deal(n, m);
216     }
217 
218     return 0;
219 }


——written by Lyon

 

posted @ 2012-09-12 12:14  LyonLys  阅读(248)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3