HDOJ-2871(线段树)

来源:互联网 发布:北京匡恩网络的董事 编辑:程序博客网 时间:2024/06/03 20:15

真是个好题,虽然WA了好几次,但都是自己SB。。。

包含了线段树所有的操作,看了这篇博文又加深了一次理解:

http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html

掉进的坑:

(1)因为每reset一次,就重新build一次,TLE,看了discuss才想起来,同一个case中reset,用update就行了

(2)build写在每个case的最前面,但忘了清空vector了,WA了好几次才想起来

(3)case之间忘了空行,PE了一次。。。


#include <cstdio>#include <vector>#include <algorithm>using namespace std;#define MAX 50005int N, M;struct Node{int l, r;int tlen, llen, rlen;int mark;int mid(){ return (l+r)>>1; }int len(){ return r-l+1; }} node[MAX << 2];struct Range{int l, r;Range(): l(0), r(0){}Range(const Range& r): l(r.l), r(r.r){}bool operator < (int x)const{return r < x;}};vector<Range> used;inline void pushDown(int x){if(node[x].mark != -1) node[x<<1].mark = node[x<<1|1].mark = node[x].mark;}inline void pushUp(int x){if(node[x<<1].mark == node[x<<1|1].mark) node[x].mark = node[x<<1].mark;else node[x].mark = -1;node[x].tlen = max(node[x<<1].rlen+node[x<<1|1].llen,    max(node[x<<1].tlen, node[x<<1|1].tlen)   );if(node[x<<1].llen == node[x<<1].len())node[x].llen = node[x<<1].llen + node[x<<1|1].llen;elsenode[x].llen = node[x<<1].llen;if(node[x<<1|1].rlen == node[x<<1|1].len())node[x].rlen = node[x<<1|1].rlen + node[x<<1].rlen;elsenode[x].rlen = node[x<<1|1].rlen;}void update(int x, int L, int R, int tag){if(node[x].l >= L && node[x].r <= R){if(tag) node[x].tlen = node[x].llen = node[x].rlen = 0;else node[x].tlen = node[x].llen = node[x].rlen = node[x].len();node[x].mark = tag;}else{pushDown(x);int m = node[x].mid();if(m >= R) update(x<<1, L, R, tag);else if(m < L) update(x<<1|1, L, R, tag);else{update(x<<1, L, m, tag);update(x<<1|1, m+1, R, tag);}pushUp(x);}}void build(int x, int l, int r){node[x].l = l;node[x].r = r;node[x].mark = 0;node[x].tlen = node[x].llen = node[x].rlen = node[x].len();if(l == r) return;int m = node[x].mid();build(x<<1, l, m);build(x<<1|1, m+1, r);}int alloc(int x, int n){int lc = x<<1, rc = x<<1|1;//check starting from left endif(node[x].llen >= n){return node[x].l;}//check left subtreeif(node[lc].tlen >= n){return alloc(lc, n);}//check left + rightif(node[lc].rlen + node[rc].llen >= n){return node[lc].r-node[lc].rlen+1;}//check right subtreeif(node[rc].tlen >= n){return alloc(rc, n);}//should never reach herereturn 0;}int New(int n){if(n <= 0 || node[1].tlen < n) return 0;Range block;block.l = alloc(1, n);block.r = block.l+n-1;int i = lower_bound(used.begin(), used.end(), block.l) - used.begin();used.insert(used.begin() + i, block);update(1, block.l, block.r, 1);return block.l;}Range Free(int x){if(used.empty()) return Range();//find block that contains xint i = lower_bound(used.begin(), used.end(), x) - used.begin();if(i >= used.size() || used[i].l > x) return Range();//mark the range unusedRange res = used[i];update(1, used[i].l, used[i].r, 0);used.erase(used.begin() + i);return res;}int Get(int n){if(n < 1 || n > used.size()) return 0;return used[n-1].l;}void Reset(){for(int i = 0; i < used.size(); ++i){update(1, used[i].l, used[i].r, 0);}used.clear();}int main(){int s, n;char cmd[8];Range block;while(~scanf("%d%d", &N, &M)){build(1, 1, N);while(M--){scanf("%s", cmd);if(cmd[0] == 'N'){scanf("%d", &n);s = New(n);if(s) printf("New at %d\n", s);else puts("Reject New");}else if(cmd[0] == 'F'){scanf("%d", &n);block = Free(n);if(block.l) printf("Free from %d to %d\n", block.l, block.r);else puts("Reject Free");}else if(cmd[0] == 'G'){scanf("%d", &n);s = Get(n);if(s) printf("Get at %d\n", s);else puts("Reject Get");}else{puts("Reset Now");Reset();}}puts("");}return 0;}


0 0
原创粉丝点击