HDOJ-2871(線段樹)

真是個好題,雖然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 	50005

int 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;
	else
		node[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;
	else
		node[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 end
	if(node[x].llen >= n){
		return node[x].l;
	}
	//check left subtree
	if(node[lc].tlen >= n){
		return alloc(lc, n);
	}
	//check left + right
	if(node[lc].rlen + node[rc].llen >= n){
		return node[lc].r-node[lc].rlen+1;
	}
	//check right subtree
	if(node[rc].tlen >= n){
		return alloc(rc, n);
	}

	//should never reach here
	return 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 x
	int i = lower_bound(used.begin(), used.end(), x) - used.begin();
	if(i >= used.size() || used[i].l > x) return Range();

	//mark the range unused
	Range 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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章