【BZOJ 3050】【USACO2013 Jan】Seating 线段树
线段树维护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个标记维护区间内奶牛个数,左端最长连续空位,右端最长连续空位,区间内最长连续空位,然后就没了。
NOI 2017 Bless All