zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    MP3 Lame 转换 参数 设置(转)
    数据库SQL优化大总结之 百万级数据库优化方案(转)
    IndexedDB:浏览器里内置的数据库(转)
    【译】微型ORM:PetaPoco【不完整的翻译】(转)
    'NoneType' object has no attribute '__getitem__'
    关于python的整形(int)自动转长整形(long)的问题
    1-redis使用笔记
    Flask deployment on gunicorn with flask script
    Celery从入门到放弃
    SELECT中的CAST
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_2871_Lyon.html
Copyright © 2011-2022 走看看