hdu 2871 Memory Control

神题啊。。。神题总是被这么多人虐。。也虐了这么多人。。。

依旧线段树。

内存操作,读题需仔细。。。

一个地方没考虑全,结果RE死了。。。后改了,然后一个地方想错,结果WA死了。。。

结点里记录的是,从左端起连续的空白个数,右端起,以及这个区间最大的连续空白处,用于NEW操作。

然后cover是记录当前区间是否全为空白(0),或者全被覆盖(1),或者二者混合(-1)

id记录当前区间对应的a 数组,a数组记录的是操作的起始点,id 用于 FREE操作,得到当前单元的区间值。

id 为 -2 表示空白, -1 为混合色,其他为有效id。

用了个vector,记录有效内存块的起始点,用于GET操作,可以sort 后二分位置,动态删除。


细节写清楚就没什么了。不仅需要更新cover 还需要更新id。。。囧啊。。。这个更新整死我了。。。><。。。不过对成段更新又理解了些。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=(s); i<(t); i++)
#define BUG puts("here!!!")
#define STOP system("pause")
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)

using namespace std;

const int MAX = 50010;
struct Tnode{				// 一维线段树 
    int l,r,lval, rval, max, cover, id;
    int len() { return r - l;}
    int mid() { return MID(l,r);}
    bool in(int ll,int rr) { return l >= ll && r <= rr; }
    void lr(int ll,int rr){ l = ll; r = rr;}
};
Tnode node[MAX<<2];
void Build(int t,int l,int r)
{
	node[t].lr(l,r);
	node[t].lval = node[t].rval = node[t].max = r - l;
	node[t].cover = 0;
	node[t].id = -2;			// -2 空白 -1 杂色 
	if( node[t].len() == 1 ) return ;
	int mid = MID(l,r);
	Build(L(t),l,mid);
	Build(R(t),mid,r);
}

void Updata_val(int t)
{
	node[t].lval = node[L(t)].lval;
	if( node[L(t)].lval == node[L(t)].len() )
		node[t].lval += node[R(t)].lval;
	
	node[t].rval = node[R(t)].rval;
	if( node[R(t)].rval == node[R(t)].len() )
		node[t].rval += node[L(t)].rval;
	
	node[t].max = max(node[L(t)].max, max(node[L(t)].rval + node[R(t)].lval, node[R(t)].max));
	node[t].max = max(node[t].max, max(node[t].lval, node[t].rval));
}

void Updata_cover(int t)
{
	if( node[L(t)].cover == node[R(t)].cover )
		node[t].cover = node[L(t)].cover;
	else
		node[t].cover = -1;
		
	if( node[L(t)].id == node[R(t)].id )
		node[t].id = node[L(t)].id;
	else
		node[t].id = -1;
}

void Push_val(int t, int val, int id)
{
	node[t].cover = val;
	node[t].lval = node[t].rval = node[t].max = (val ? 0 : node[t].len());
	if( id != -1 )
		node[t].id = id;
}
void Push_down(int t)
{
	if( node[t].len() == 1 ) return ;
	if( node[t].cover != -1 )
	{
		Push_val(L(t), node[t].cover, node[t].id);
		Push_val(R(t), node[t].cover, node[t].id);
	}
}

void Updata(int t,int l,int r,int val, int id)
{
	Push_down(t);
	if( node[t].in(l,r) )
	{
		node[t].id = id;
		Push_val(t, val, id);
		return ;
	}
	if( node[t].len() == 1 ) return ;
	int mid = node[t].mid();
	if( l < mid ) Updata(L(t),l,r,val,id);
	if( r > mid ) Updata(R(t),l,r,val,id);
	Updata_val(t);
	Updata_cover(t);
}

int Query(int t, int val)
{
	Push_down(t);
	if( node[t].max == node[t].len() && node[t].max >= val )
		return node[t].l;
	
	if( node[t].len() == 1 ) return -1;
	
	if( node[L(t)].max >= val )
		return Query(L(t), val);
	if( node[L(t)].rval + node[R(t)].lval >= val )	
		return node[L(t)].r - node[L(t)].rval;
	if( node[R(t)].max >= val )
		return Query(R(t), val);
	return -1;
}

void Query_id(int t, int l, int r, int &pos)
{
	Push_down(t);
	if( node[t].cover != -1 && node[t].id >= 0 && l >= node[t].l && r <= node[t].r )
	{
		pos = node[t].id;
		return ;
	}
	if( node[t].len() == 1 ) return ;
	int mid = node[t].mid();
	if( l < mid ) Query_id(L(t),l,r,pos);
	if( r > mid ) Query_id(R(t),l,r,pos);
	Updata_val(t);
	Updata_cover(t);
}

int a[MAX][2];
vector<int> v;
int main()
{
	int n, m, len, cnt, ind;
	char s[10];
	while( ~scanf("%d%d", &n, &m) )
	{
		v.clear();
		Build(1, 0, n);
		cnt = ind = 0;
		while( m-- )
		{
			scanf("%s", s);
			if( s[0] == 'R' )
			{
				puts("Reset Now");
				Updata(1, 0, n, 0, -2);
				cnt = ind = 0;
				v.clear();
				continue;
			}
			
			scanf("%d", &len);
			if( s[0] == 'N' )
			{
				int pos = Query(1, len);
				if( pos == -1 )
					puts("Reject New");
				else
				{
					Updata(1, pos, pos+len, 1, ind);
					printf("New at %d\n", pos+1);
					a[ind][0] = pos;
					a[ind++][1] = pos + len;
					v.push_back( pos );
					cnt++;
				}
				continue;
			}
			
			if( s[0] == 'G' )
			{
				if( cnt < len )
					puts("Reject Get");
				else
				{
					sort(v.begin(), v.end());
					int pos = v[len-1];
					printf("Get at %d\n", pos + 1);
				}
				continue;
			}
			
			int pos = -1;
			Query_id(1, len-1, len, pos);
			if( pos < 0 )
				puts("Reject Free");
			else
			{
				Updata(1, a[pos][0], a[pos][1], 0, -2);
				printf("Free from %d to %d\n", a[pos][0] + 1, a[pos][1]);
				cnt--;
				sort(v.begin(), v.end());
				v.erase( lower_bound(v.begin(), v.end(), a[pos][0]) );
			}
		}
		puts("");
	}

return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值