HDU 2871 Memory Control
裸线段树区间合并,一开始没注意题目细节结果搞麻烦了……
给你四种操作,每种操作按它的要求输出结果。
1. Reset Reset all memory units free.
Reset 释放所有的内存
2. New x Allocate a memory block consisted of x continuous free memory units with the least start number
New x 申请一个包含x个连续内存单元的内存块,起始地址编号最小
3. Free x Release the memory block which includes unit x
Free x 释放包含地址x的内存块
(这个地方有个注意点可以从样例中得到,就是说如果我先申请了内存块1-2,后申请了内存块3-4,虽然1-4此时都被申请了,但1-4并不属于一个连续的内存块,因为它不是被一次申请的。如果查询4所在的内存块的起始地址,应当输出3,而不是1 )
4. Get x Return the start number of the xth memory block(Note that we count the memory blocks allocated from left to right)
Get x 返回第x个内存块的起始地址(假定我们将内存块从左到右编号)
因为把题意的细节理解的有问题,所以一开始我的线段树不只是记录了连续的空余区间长度,还把连续被申请的区间长度也记录了,事实证明这是完全没必要。然后就去掉了。
还有一个地方是用一个vector来记录一下已经申请的内存块,因为要用二分查找,所以在向vector中插入元素时应注意维护一下它的有序性。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <vector> 6 7 using namespace std; 8 9 #define lc rt << 1 10 #define rc rt << 1 | 1 11 #define lson l, m, rt << 1 12 #define rson m + 1, r, rt << 1 | 1 13 14 const int MAXN = 50002; 15 16 struct node 17 { 18 int st, ed; 19 node(){} 20 node( int _st, int _ed ) : st( _st ), ed( _ed ) { } 21 }; 22 23 vector<node> blocks; 24 25 int N, Q; 26 int len[ MAXN << 2 ]; //空闲区最长连续长度 27 28 int Llen[ MAXN << 2 ]; //左端空闲区长度 29 int Rlen[ MAXN << 2 ]; //右端空闲区长度 30 31 int flag[ MAXN << 2 ]; //0 释放 -1 无标记 1 占用 32 33 bool lbd[ MAXN << 2 ]; //左端点是否空闲 34 bool rbd[ MAXN << 2 ]; //右端点是否空闲 35 36 void chuli( int op, int rt, int l, int r ) 37 { 38 if ( op == 0 ) 39 Llen[rt] = Rlen[rt] = len[rt] = r - l + 1; 40 else 41 Llen[rt] = Rlen[rt] = len[rt] = 0; 42 43 lbd[rt] = rbd[rt] = op ^ 1; 44 return; 45 } 46 47 void PushDown( int rt, int l, int r, int m ) 48 { 49 if ( flag[rt] != -1 ) 50 { 51 flag[lc] = flag[rc] = flag[rt]; 52 chuli( flag[lc], lc, l, m ); 53 chuli( flag[rc], rc, m + 1, r ); 54 flag[rt] = -1; 55 } 56 return; 57 } 58 59 void PushUp( int rt, int l, int r, int m ) 60 { 61 lbd[rt] = lbd[lc]; 62 rbd[rt] = rbd[rc]; 63 64 Llen[rt] = Llen[lc]; 65 Rlen[rt] = Rlen[rc]; 66 67 if ( Llen[lc] == m - l + 1 ) Llen[rt] += Llen[rc]; 68 if ( Rlen[rc] == r - m ) Rlen[rt] += Rlen[lc]; 69 70 len[rt] = max( len[lc], len[rc] ); 71 if ( lbd[rc] && rbd[lc] ) len[rt] = max( len[rt], Llen[rc] + Rlen[lc] ); 72 73 return; 74 } 75 76 void build( int l, int r, int rt ) 77 { 78 flag[rt] = -1; 79 if ( l == r ) 80 { 81 len[rt] = Llen[rt] = Rlen[rt] = 1; 82 lbd[rt] = rbd[rt] = true; 83 return; 84 } 85 86 int m = ( l + r ) >> 1; 87 build( lson ); 88 build( rson ); 89 PushUp( rt, l, r, m ); 90 91 return; 92 } 93 94 void Update( int L, int R, int op, int l, int r, int rt ) 95 { 96 int m = ( l + r ) >> 1; 97 if ( L <= l && r <= R ) 98 { 99 flag[rt] = op; 100 chuli( op, rt, l, r ); 101 return; 102 } 103 PushDown( rt, l, r, m ); 104 105 if ( L <= m ) Update( L, R, op, lson ); 106 if ( R > m ) Update( L, R, op, rson ); 107 108 PushUp( rt, l, r, m ); 109 110 return; 111 } 112 113 int Query( int a, int op, int l, int r, int rt ) //op代表查询空闲区间还是占用区间 114 { 115 int m = ( l + r ) >> 1; 116 117 if ( l == r ) 118 { 119 if ( len[rt] == a ) return l; 120 else return 0; 121 } 122 123 PushDown( rt, l, r, m ); 124 125 if ( len[lc] >= a ) return Query( a, op, lson ); 126 else if ( Rlen[lc] + Llen[rc] >= a ) return m - Rlen[lc] + 1; 127 else if ( len[rc] >= a ) return Query( a, op, rson ); 128 else return 0; 129 } 130 131 int BiSearch( int tar ) 132 { 133 int low = 0, high = blocks.size() - 1, mid; 134 while ( low <= high ) 135 { 136 mid = ( low + high ) >> 1; 137 if ( blocks[mid].st <= tar ) low = mid + 1; 138 else high = mid - 1; 139 } 140 return low; 141 } 142 143 int main() 144 { 145 while ( ~scanf( "%d%d", &N, &Q ) ) 146 { 147 build( 1, N, 1 ); 148 blocks.clear(); 149 while ( Q-- ) 150 { 151 char oper[10]; 152 int a, idx; 153 scanf( "%s", oper ); 154 if ( oper[0] == 'R' ) 155 { 156 Update( 1, N, 0, 1, N, 1 ); 157 blocks.clear(); 158 puts("Reset Now"); 159 } 160 else 161 { 162 scanf( "%d", &a ); 163 switch( oper[0] ) 164 { 165 case 'N': 166 if ( len[1] < a ) puts("Reject New"); 167 else 168 { 169 int st = Query( a, 0, 1, N, 1 ); 170 printf( "New at %d\n", st ); 171 idx = BiSearch( st ); 172 blocks.insert( blocks.begin() + idx, node( st, st + a - 1 ) ); 173 Update( st, st + a - 1, 1, 1, N, 1 ); 174 } 175 break; 176 177 case 'F': 178 idx = BiSearch(a) - 1; 179 if ( idx == -1 || a > blocks[idx].ed ) puts("Reject Free"); 180 else 181 { 182 printf( "Free from %d to %d\n", blocks[idx].st, blocks[idx].ed ); 183 Update( blocks[idx].st, blocks[idx].ed, 0, 1, N, 1 ); 184 blocks.erase( blocks.begin() + idx, blocks.begin() + idx + 1 ); 185 } 186 break; 187 188 case 'G': 189 --a; 190 if ( a >= (int)blocks.size() ) puts("Reject Get"); 191 else printf( "Get at %d\n", blocks[a].st ); 192 break; 193 } 194 } 195 } 196 puts(""); 197 } 198 return 0; 199 }