为了查找标号最小的可用的block可以用一个以block标号为关键字的最小堆实现,同时为了能够修改正在使用的block延续的时间以及适时free过时的block,可以另外开一个以block开始使用的时刻为关键字的最小堆。
#include<stdio.h> #include<string.h> #define MAXD 30010 #define INF 0x3f3f3f3f const int N = 30000, T = 600; int now, M, u[4 * MAXD], t[4 * MAXD], last[2 * MAXD]; char b[5]; void build() { int i, j, k; for(M = 1; M < N + 2; M <<= 1); memset(u, 0x3f, sizeof(u)); memset(last, 0x3f, sizeof(last)); memset(t, 0, sizeof(t)); for(i = 1; i <= N; i ++) u[i + M] = i; for(i = M - 1; i >= 0; i --) u[i] = u[i << 1] < u[(i << 1) | 1] ? u[i << 1] : u[(i << 1) | 1]; } void ufresh(int i) { for(; i ^ 1; i >>= 1) u[i >> 1] = u[i] < u[i ^ 1] ? u[i] : u[i ^ 1]; } void tfresh(int i) { for(; i ^ 1; i >>= 1) t[i >> 1] = last[t[i]] < last[t[i ^ 1]] ? t[i] : t[i ^ 1]; } void Delete() { int k; while((k = t[1]) && now - last[t[1]] >= T) { t[k + M] = 0, tfresh(k + M); u[k + M] = k, ufresh(k + M); } } void solve() { int k; scanf("%s", b); Delete(); if(b[0] == '+') { k = u[1]; printf("%d\n", k); u[k + M] = INF, ufresh(k + M); last[k] = now, t[k + M] = k, tfresh(k + M); } else { scanf("%d", &k); if(t[k + M] == 0) printf("-\n"); else { printf("+\n"); last[k] = now, tfresh(k + M); } } } int main() { build(); while(scanf("%d", &now) == 1) { solve(); } return 0; }