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