您的位置:首页 > 其它

【BZOJ 3050】【USACO2013 Jan】Seating 线段树

2016-03-30 11:25 417 查看
线段树维护4个标记,

昨天互测时题意理解错了,今天上午才发现。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 500003
using namespace std;
int sum[N*3], n, m, ans = 0, lazy[N*3],left[N*3],right[N*3],whole[N*3];
inline void buildtree(int l, int r, int rt) {
sum[rt] = 0;
lazy[rt] = 0;
left[rt] = r - l + 1;
right[rt] = r - l + 1;
whole[rt] = r - l + 1;
if (l == r)
return;
int mid = (l + r) >> 1;
buildtree(l, mid, rt << 1);
buildtree(mid + 1, r, rt << 1 | 1);
}
inline void pushdown(int l, int r, int rt) {
if (lazy[rt] != 0) {
if (lazy[rt] == 1) {
lazy[rt] = 0;
lazy[rt << 1] = 1;
lazy[rt << 1 | 1] = 1;
int mid = (l + r) >> 1;
sum[rt << 1] = mid - l + 1;
left[rt << 1] = 0;
right[rt << 1] = 0;
whole[rt << 1] = 0;
sum[rt << 1 | 1] = r - mid;
left[rt << 1 | 1] = 0;
right[rt << 1 | 1] = 0;
whole[rt << 1 | 1] = 0;
} else {
lazy[rt] = 0;
lazy[rt << 1] = -1;
lazy[rt << 1 | 1] = -1;
int mid = (l + r) >> 1;
sum[rt << 1] = 0;
left[rt << 1] = mid - l + 1;
right[rt << 1] = mid - l + 1;
whole[rt << 1] = mid - l + 1;
sum[rt << 1 | 1] = 0;
left[rt << 1 | 1] = r - mid;
right[rt << 1 | 1] = r - mid;
whole[rt << 1 | 1] = r - mid;
}
}
}
inline void pushup(int rt){
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
left[rt] = sum[rt << 1] == 0 ? whole[rt << 1] + left[rt << 1 | 1] : left[rt << 1];
right[rt] = sum[rt << 1 | 1] == 0 ? whole[rt << 1 | 1] + right[rt << 1] : right[rt << 1 | 1];
whole[rt] = max(whole[rt << 1], whole[rt << 1 | 1]);
whole[rt] = max(whole[rt], right[rt << 1] + left[rt << 1 | 1]);
}
inline void clr(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
sum[rt] = 0;
left[rt] = r - l + 1;
right[rt] = r - l + 1;
whole[rt] = r - l + 1;
lazy[rt] = -1;
return;
}
pushdown(l, r, rt);
int mid = (l + r) >> 1;
if (L <= mid)
clr(L, R, l, mid, rt << 1);
if (R > mid)
clr(L, R, mid + 1, r, rt << 1 | 1);
pushup(rt);
}
inline void put(int L, int R, int l, int r, int rt) {
if (L <=l && r <= R) {
sum[rt] = r - l + 1;
left[rt] = 0;
right[rt] = 0;
whole[rt] = 0;
lazy[rt] = 1;
return;
}
pushdown(l, r, rt);
int mid = (l + r) >> 1;
if (L <= mid)
put(L, R, l, mid, rt << 1);
if (R > mid)
put(L, R, mid + 1, r, rt << 1 | 1);
pushup(rt);
}
inline void add(int num, int l, int r, int rt) {
if (l == r) {
put(l, r, 1, n, 1);
return;
}
int mid = (l + r) >> 1;
if (whole[rt << 1] >= num)
add(num, l, mid, rt << 1);
else
if (right[rt << 1] + left[rt << 1 | 1] >= num)
put(mid + 1 - right[rt << 1], mid - right[rt << 1] + num, 1, n, 1);
else
add(num, mid + 1, r, rt << 1 | 1);
}
int main() {
scanf("%d%d\n", &n, &m);
buildtree(1, n, 1);
char c;
int a, b;
while (m--) {
for(c = getchar(); c != 'A' && c != 'L'; c = getchar());
if (c == 'A') {
scanf("%d\n", &a);
if (whole[1] < a)
++ans;
else
add(a, 1, n, 1);
} else {
scanf("%d%d\n", &a, &b);
clr(a, b, 1, n, 1);
}
}
printf("%d\n",ans);
return 0;
}


4个标记维护区间内奶牛个数,左端最长连续空位,右端最长连续空位,区间内最长连续空位,然后就没了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: