【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个标记维护区间内奶牛个数,左端最长连续空位,右端最长连续空位,区间内最长连续空位,然后就没了。

转载于:https://www.cnblogs.com/abclzr/p/5336419.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值