神题。。综合了线段树的所有操作,很锻炼代码能力。
初状态全为0
ls,ms,rs记录区间连续的0,lv,rv记录其所属block的左右端点,c为其懒标记,
cnt记录区间的block数,clr记录是否重置。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define lson l , m , rt<<1
#define rson m+1,r , rt<<1|1
using namespace std;
typedef long long LL;
const int maxn = 80005;
struct SegTree{
int ls[maxn<<2],ms[maxn<<2],rs[maxn<<2],c[maxn<<2];
int cnt[maxn<<2],clr[maxn<<2];
int lv[maxn<<2],rv[maxn<<2];
void push_up(int l,int r,int rt){
int m = (l + r) >> 1;
ms[rt] = max(max(ms[rt<<1],ms[rt<<1|1]),rs[rt<<1]+ls[rt<<1|1]);
ls[rt] = ls[rt<<1] == m-l+1 ? ls[rt<<1]+ls[rt<<1|1] : ls[rt<<1];
rs[rt] = rs[rt<<1|1] == r-m ? rs[rt<<1|1]+rs[rt<<1] : rs[rt<<1|1];
}
void push_down(int l,int r,int rt){
if(c[rt] == -1) return;
int m = (l + r) >> 1;
c[rt<<1] = c[rt<<1|1] = c[rt];
if(c[rt]) ms[rt<<1] = ls[rt<<1] = rs[rt<<1] =
ms[rt<<1|1] = ls[rt<<1|1] = rs[rt<<1|1] = 0;
else{
ms[rt<<1] = ls[rt<<1] = rs[rt<<1] = m-l+1;
ms[rt<<1|1] = ls[rt<<1|1] = rs[rt<<1|1] = r-m;
}
lv[rt<<1] = lv[rt<<1|1] = lv[rt];
rv[rt<<1] = rv[rt<<1|1] = rv[rt];
c[rt] = -1;
}
void cnt_up(int rt){
cnt[rt] = cnt[rt<<1] + cnt[rt<<1|1];
}
void clear(int l,int r,int rt){
if(clr[rt] == 0) return;
clr[rt<<1] = clr[rt<<1|1] = clr[rt];
cnt[rt<<1] = cnt[rt<<1|1] = clr[rt] = 0;
}
void build(int l,int r,int rt){
c[rt] = lv[rt] = rv[rt] = -1;clr[rt] = cnt[rt] = 0;
if(l == r){
ls[rt] = ms[rt] = rs[rt] = 1;
return;
}
int m = (l + r) >> 1;
build(lson);build(rson);
push_up(l,r,rt);
}
int New(int x,int l,int r,int rt){
if(ms[rt] < x) return -1;
if(l == r) return l;
push_down(l,r,rt);
int m = (l + r) >> 1;
if(ms[rt<<1] >= x) return New(x,lson);
else if(rs[rt<<1]+ls[rt<<1|1] >= x) return m-rs[rt<<1]+1;
else return New(x,rson);
}
int Free(int x,int l,int r,int rt){
if(l == r) return rt;
push_down(l,r,rt);
int m = (l + r) >> 1;
if(m >= x) return Free(x,lson);
else return Free(x,rson);
}
int Get(int x,int l,int r,int rt){
if(cnt[rt] < x) return -1;
if(l == r) return l;
clear(l,r,rt);
int m = (l + r) >> 1;
if(cnt[rt<<1] >= x) return Get(x,lson);
else return Get(x-cnt[rt<<1],rson);
}
void MemFill(int a,int b,int x,int l,int r,int rt){
if(l > b || r < a) return;
if(a <= l && r <= b){
ms[rt] = ls[rt] = rs[rt] = x ? 0 : r-l+1;
lv[rt] = x ? a : -1;
rv[rt] = x ? b : -1;
c[rt] = x;
return;
}
push_down(l,r,rt);
int m = (l + r) >> 1;
MemFill(a,b,x,lson);MemFill(a,b,x,rson);
push_up(l,r,rt);
}
void update(int k,int x,int l,int r,int rt){
if(l == r){
cnt[rt] = x;
return;
}
clear(l,r,rt);
int m = (l + r) >> 1;
if(m >= k) update(k,x,lson);
else update(k,x,rson);
cnt_up(rt);
}
}sol;
int main(){
int n,q,x;char ch[10];
while(~scanf("%d%d",&n,&q)){
sol.build(1,n,1);
while(q--){
scanf("%s",ch);
if(ch[0] == 'R'){
sol.cnt[1] = 0;
sol.clr[1] = 1;
sol.MemFill(1,n,0,1,n,1);
printf("Reset Now\n");
}else{
scanf("%d",&x);
if(ch[0] == 'N'){
int pos = sol.New(x,1,n,1);
if(pos == -1) printf("Reject New\n");
else{
sol.MemFill(pos,pos+x-1,1,1,n,1);
sol.update(pos,1,1,n,1);
printf("New at %d\n",pos);
}
}else if(ch[0] == 'F'){
int pos = sol.Free(x,1,n,1);
if(sol.lv[pos] < 0) printf("Reject Free\n");
else{
printf("Free from %d to %d\n",sol.lv[pos],sol.rv[pos]);
sol.update(sol.lv[pos],0,1,n,1);
sol.MemFill(sol.lv[pos],sol.rv[pos],0,1,n,1);
}
}else{
int pos = sol.Get(x,1,n,1);
if(pos == -1) printf("Reject Get\n");
else printf("Get at %d\n",pos);
}
}
}
putchar('\n');
}
return 0;
}