题意:就是对一个区间的四种操作,NEW x,占据最左边的连续的x个单元,Free x 把x单元所占的连续区间清空 , Get x 把第x次占据的区间输出来, R 清空整个区间。
解法:很明显的区间合并,跟hotel那题差不多,貌似多了Free,Get操作,
我们可以用一个vector保存已经申请的区间,然后要Free x就在vector里面二分找到x所在的区间即可, Get也是二分一下即可, 其它操作可以用线段树或者伸展树操作。
这题主要是练了一下伸展树,这题也算基础, 但还是调了好久,真心难调,锻炼调试能力。
伸展树:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 50006;
#define L ch[x][0]
#define R ch[x][1]
#define KT ch[ ch[root][1]][0]
#define mp make_pair
typedef pair<int, int> pii;
int n;
struct splayTree {
int sz[maxn], pre[maxn], ch[maxn][2];
int top, root;
int ls[maxn], rs[maxn], ms[maxn], col[maxn], val[maxn];
void rotate(int &x, int f) {
int y = pre[x], z = pre[y];
down(y); down(x);
ch[y][!f] = ch[x][f];
pre[ch[x][f]] = y;
pre[x] = pre[y];
if(z) ch[z][ch[z][1] == y] = x;
ch[x][f] = y;
pre[y] = x;
up(y);
}
void splay(int &x, int g) {
down(x);
while(pre[x] != g) {
int y = pre[x], z = pre[y];
if(z == g) rotate(x, ch[y][0] == x);
else {
int f = (ch[z][0] == y);
ch[y][!f] == x ? rotate(y, f) : rotate(x, !f);
rotate(x, f);
}
}
up(x);
if(!g) root = x;
}
void rto(int k, int g) {
int x = root;
while(sz[L] != k) {
down(x);
if(sz[L] > k) x = L;
else {
k -= sz[L]+1;
x = R;
}
}
splay(x, g);
}
void newNode(int &x, int v, int fa) {
x = ++top;
sz[x] = 1;
pre[x] = fa;
L = R = 0;
col[x] = -1;
ls[x] = rs[x] = ms[x] = val[x] = v;
}
void down(int x) {
if(~col[x]) {
col[L] = col[R] = val[L] = val[R] = col[x];
ls[L] = rs[L] = ms[L] = col[x] * sz[L];
ls[R] = rs[R] = ms[R] = col[x] * sz[R];
col[x] = -1;
}
}
void up(int x) {
sz[x] = sz[L] + sz[R] + 1;
ls[x] = ls[L];
rs[x] = rs[R];
ms[x] = max(ms[L], ms[R]);
if(val[x]) {
ms[x] = max(ms[x], rs[L]+1+ls[R]);
if(ls[x] == sz[L]) ls[x] += ls[R]+1;
if(rs[x] == sz[R]) rs[x] += rs[L]+1;
}
}
void build(int &x, int l, int r, int fa) {
if(l > r) return;
int m = (l + r) >> 1;
newNode(x, 1, fa);
build(L, l, m-1, x);
build(R, m+1, r, x);
up(x);
}
void init(int n) {
top = 0;
newNode(root, 0, 0);
newNode(ch[root][1], 0, root);
build(KT, 0, n-1, ch[root][1]);
up(ch[root][1]); up(root);
}
void update(int l, int r, int c) {
rto(l-1, 0);
rto(r+1, root);
col[KT] = val[KT] = c;
ls[KT] = rs[KT] = ms[KT] = c*sz[KT];
up(ch[root][1]);
up(root);
}
int find(int x, int k, int pos) { //找连续的空位的首位置
down(x);
if(ms[L] >= k) return find(L, k, pos);
pos += sz[L];
if(val[x] && rs[L]+ls[R]+1 >= k) return pos - rs[L];
return find(R, k, pos+1);
}
}spt;
vector<pii> vec;
int main() {
char op[22];
int j, m, x;
while (~scanf("%d%d", &n, &m)) {
spt.init(n);
vec.clear();
while (m--) {
scanf("%s", op);
if (op[0] == 'R') {
vec.clear();
puts("Reset Now");
spt.update(1, n, 1);
continue;
}
scanf("%d", &x);
if (op[0] == 'N') {
if (spt.ms[spt.root] < x) {
puts("Reject New");
continue;
}
int l = spt.find(spt.root, x, 0);
printf("New at %d\n", l);
int r = l + x - 1;
spt.update(l, r, 0);
pii tp = mp(l, r);
j = lower_bound(vec.begin(), vec.end(), tp) - vec.begin();
vec.insert(vec.begin() + j, tp);
} else if (op[0] == 'G') {
if ((int) vec.size() < x)
puts("Reject Get");
else
printf("Get at %d\n", vec[x - 1].first);
} else if (op[0] == 'F') {
j = upper_bound(vec.begin(), vec.end(), mp(x, n + 3))
- vec.begin() - 1;
if (j == -1 || vec[j].first > x || vec[j].second < x)
puts("Reject Free");
else {
printf("Free from %d to %d\n", vec[j].first, vec[j].second);
spt.update(vec[j].first, vec[j].second, 1);
vec.erase(vec.begin() + j);
}
}
}
puts("");
}
return 0;
}
线段树:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 50006;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define ls rt<<1
#define rs rt<<1|1
#define Mid int m = (l+r) >> 1
#define mp make_pair
typedef pair<int, int> pii;
int n;
struct segTree {
int lsum[maxn<<2], rsum[maxn<<2], msum[maxn<<2];
int col[maxn<<2];
inline void up(int l, int r, int rt) {
msum[rt] = max(msum[ls], msum[rs]);
msum[rt] = max(msum[rt], rsum[ls] + lsum[rs]);
Mid;
lsum[rt] = lsum[ls];
if (lsum[ls] == m - l + 1) lsum[rt] += lsum[rs];
rsum[rt] = rsum[rs];
if (lsum[rs] == r - m) rsum[rt] += rsum[ls];
}
inline void down(int l, int r, int rt) {
if (~col[rt]) {
col[ls] = col[rs] = col[rt];
Mid;
lsum[ls] = rsum[ls] = msum[ls] = col[rt] * (m - l + 1);
lsum[rs] = rsum[rs] = msum[rs] = col[rt]* (r - m );
col[rt] = -1;
}
}
void build(int l = 1, int r = n, int rt = 1) {
lsum[rt] = rsum[rt] = msum[rt] = r - l + 1;
col[rt] = -1;
if (l == r)
return;
Mid;
build(lson);
build(rson);
// up(l, r, rt);
}
void update(int L, int R, int v, int l = 1, int r = n, int rt = 1) {
if (L <= l && r <= R) {
col[rt] = v;
rsum[rt] = lsum[rt] = msum[rt] = v * (r - l + 1);
return;
}
Mid;
down(l, r, rt);
if (L <= m)
update(L, R, v, lson);
if (R > m)
update(L, R, v, rson);
up(l, r, rt);
}
int find(int x, int l = 1, int r = n, int rt = 1) {
if (l == r)
return l;
Mid;
down(l, r, rt);
if (msum[ls] >= x)
return find(x, lson);
else if (rsum[ls] + lsum[rs] >= x)
return m - rsum[ls] + 1;
else
return find(x, rson);
}
} tree;
vector<pii > vec;
int main() {
char op[22];
int j, m, x;
while (~scanf("%d%d", &n, &m)) {
tree.build();
vec.clear();
while (m--) {
scanf("%s", op);
if (op[0] == 'R') {
vec.clear();
puts("Reset Now");
tree.update(1, n, 1);
continue;
}
scanf("%d", &x);
if (op[0] == 'N') {
if (tree.msum[1] < x) {
puts("Reject New");
continue;
}
int l = tree.find(x);
printf("New at %d\n", l);
int r = l + x - 1;
tree.update(l, r, 0);
pii tp = mp(l, r);
j = lower_bound(vec.begin(), vec.end(), tp) - vec.begin();
vec.insert(vec.begin()+j, tp);
} else if (op[0] == 'G') {
if ((int) vec.size() < x)
puts("Reject Get");
else
printf("Get at %d\n", vec[x - 1].first);
} else if (op[0] == 'F') {
j = upper_bound(vec.begin(), vec.end(), mp(x, n + 3))
- vec.begin() - 1;
if (j == -1 || vec[j].first > x || vec[j].second < x)
//if(j == -1)
puts("Reject Free");
else {
printf("Free from %d to %d\n", vec[j].first, vec[j].second);
tree.update(vec[j].first, vec[j].second, 1);
vec.erase(vec.begin() + j);
}
}
}
puts("");
}
return 0;
}