题目来源:http://poj.org/problem?id=3667
线段树中存放六个元素:左右端点left,right。左端点向右延伸后的最大长度cl,右端点向左延伸后的最大长度cr。区间内的最大连续长度maxl。lazy操作的标签add。
从上向下更新,如果覆盖段就打lazy标记,遍历到有lazy标记的线段就将lazy标记pushdown一层。
从下向上两两合并,最大连续长度可能来自左段、右端,或是贯穿左右段。
操作详见代码:
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5+10;
int n,m;
struct tree {
int left, right, maxl, cl, cr, add;
}c[maxn<<2];
int max(int a,int b,int c) {
return max(a, max(b, c));
}
void build(int id,int l,int r) {
c[id].left = l;
c[id].right = r;
c[id].maxl = c[id].cl = c[id].cr = r - l + 1;
if (l == r) return;
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
}
void pushdown(int id) {
if (c[id].right == c[id].left)return;
if (c[id].add == -1) {
c[id].add = 0;
c[id << 1].maxl = c[id << 1].cl = c[id << 1].cr = 0;
c[id << 1 | 1].maxl = c[id << 1 | 1].cr = c[id << 1 | 1].cl = 0;
c[id << 1].add = c[id << 1 | 1].add = -1;
} else {
c[id].add = 0;
c[id << 1].maxl = c[id << 1].cl = c[id << 1].cr = c[id << 1].right - c[id << 1].left + 1;
c[id << 1 | 1].maxl = c[id << 1 | 1].cr = c[id << 1 | 1].cl = c[id << 1 | 1].right - c[id << 1 | 1].left + 1;
c[id << 1].add = c[id << 1 | 1].add = 1;
}
}
int query_max(int id,int v) {
if (c[id].maxl < v)return 0;
if (c[id].add != 0)pushdown(id);
if (c[id << 1].maxl >= v)return query_max(id << 1, v);
if (c[id << 1].cr + c[id << 1 | 1].cl >= v)return ((c[id].left + c[id].right) >> 1) - c[id << 1].cr + 1;
return query_max(id << 1 | 1, v);
}
void update(int id,int l,int r,int v) {
if (c[id].left > r || c[id].right < l)return;
if (c[id].add)pushdown(id);
if (c[id].left >= l && c[id].right <= r) {
c[id].add += v;
if (v == -1)
c[id].maxl = c[id].cl = c[id].cr = 0;
else
c[id].maxl = c[id].cl = c[id].cr = c[id].right - c[id].left + 1;
return;
}
update(id << 1, l, r, v);
update(id << 1 | 1, l, r, v);
if (c[id << 1].cl == c[id << 1].right - c[id << 1].left + 1)
c[id].cl = c[id << 1].maxl + c[id << 1 | 1].cl;
else c[id].cl = c[id << 1].cl;
if (c[id << 1 | 1].cr == c[id << 1 | 1].right - c[id << 1 | 1].left + 1)
c[id].cr = c[id << 1 | 1].maxl + c[id << 1].cr;
else c[id].cr = c[id << 1 | 1].cr;
c[id].maxl = max(c[id << 1].maxl, c[id << 1 | 1].maxl, c[id << 1].cr + c[id << 1 | 1].cl);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
while (cin >> n >> m) {
build(1, 1, n);
for (int i = 1; i <= m; ++i) {
int flag;
cin >> flag;
if (flag == 1) {
int x;
cin >> x;
int t = query_max(1, x);
cout << t << endl;
if (t)update(1, t, t + x - 1, -1);
} else {
int x, d;
cin >> x >> d;
update(1, x, x + d - 1, 1);
}
}
}
return 0;
}