去年做过的题,感觉好久没写线段树了,复习一波XD。
区间合并入门题。
用三个数组维护一个区间内最大连续长度,从左一开始的最大连续长度,从右一的最大连续长度,和整个区间的最大连续长度。
细节见代码。
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <string.h>
#include <limits.h>
#include <string>
#include <iostream>
#include <queue>
#include <math.h>
#include <map>
#include <stack>
#include <sstream>
#include <set>
#include <iterator>
#include <list>
#include <cstdio>
#include <iomanip>
#include <climits>
using namespace std;
const int maxn = 5*(int)1e4+100;
int n, m, lt[maxn*4], rt[maxn*4], tVal[maxn*4], laz[maxn*4];
//laz:
// -1 unused
// 0 empty
// 1 occupied
void build(int node, int l, int r) {
tVal[node] = lt[node] = rt[node] = r - l + 1;
laz[node] = -1;
if (l == r) return;
int mid = (l + r) >> 1;
build(node<<1, l, mid);
build(node<<1|1, mid + 1, r);
}
void pushDown(int node, int l, int r) {
if (laz[node] != -1) {
int mid = (l + r) >> 1;
lt[node<<1] = rt[node<<1] = tVal[node<<1] = (laz[node] == 0 ? mid - l + 1 : 0);
lt[node<<1|1] = rt[node<<1|1] = tVal[node<<1|1] = (laz[node] == 0 ? r - mid : 0);
laz[node<<1] = laz[node<<1|1] = laz[node];
laz[node] = -1;
}
}
void pushUp(int node, int l, int r) {
int mid = (l + r) >> 1;
lt[node] = lt[node<<1];
rt[node] = rt[node<<1|1];
if (lt[node] == mid - l + 1) lt[node] += lt[node<<1|1];
if (rt[node] == r - mid) rt[node] += rt[node<<1];
tVal[node] = max(rt[node<<1] + lt[node<<1|1], max(tVal[node<<1], tVal[node<<1|1]));
}
int query(int node, int l, int r, int num) {
if (l == r) return l;
int mid = (l + r) >> 1;
pushDown(node, l, r);
if (tVal[node<<1] >= num) return query(node<<1, l, mid, num);
else if (rt[node<<1] + lt[node<<1|1] >= num) return (mid - rt[node<<1] + 1);
else return query(node<<1|1, mid + 1, r, num);
}
void goin(int node, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) {
lt[node] = rt[node] = tVal[node] = 0;
laz[node] = 1;
return;
}
pushDown(node, l, r);
int mid = (l + r) >> 1;
if (ql <= mid) goin(node<<1, l, mid, ql, qr);
if (qr > mid) goin(node<<1|1, mid + 1, r, ql, qr);
pushUp(node, l, r);
}
void goout(int node, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) {
lt[node] = rt[node] = tVal[node] = r - l + 1;
laz[node] = 0;
return;
}
pushDown(node, l, r);
int mid = (l + r) >> 1;
if (ql <= mid) goout(node<<1, l, mid, ql, qr);
if (qr > mid) goout(node<<1|1, mid + 1, r, ql, qr);
pushUp(node, l, r);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFINE
freopen("input.txt", "r", stdin);
#endif
scanf("%d%d", &n, &m);
build(1, 1, n);
for (int i = 0; i < m; ++i) {
int op, l, r, num;
scanf("%d", &op);
if (op == 1) {
scanf("%d", &num);
if (tVal[1] < num) puts("0");
else {
int pos = query(1, 1, n, num);
printf("%d\n", pos);
goin(1, 1, n, pos, pos + num - 1);
}
} else {
scanf("%d%d", &l, &num);
goout(1, 1, n, l, l + num - 1);
}
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}