神题啊。。。神题总是被这么多人虐。。也虐了这么多人。。。
依旧线段树。
内存操作,读题需仔细。。。
一个地方没考虑全,结果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;
}