zoukankan      html  css  js  c++  java
  • 【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, &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
    ", &a);
    			if (whole[1] < a)
    				++ans;
    			else
    				add(a, 1, n, 1);
    		} else {
    			scanf("%d%d
    ", &a, &b);
    			clr(a, b, 1, n, 1);
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    4个标记维护区间内奶牛个数,左端最长连续空位,右端最长连续空位,区间内最长连续空位,然后就没了。

  • 相关阅读:
    10月15日模拟赛题解
    NOIp初赛题目整理
    【meet in the mid】【qbxt2019csp刷题班day1C】birthday
    【字符串】 manacher算法
    【border树】【P2375】动物园
    【border相关】【P3426】 [POI2005]SZA-Template
    【字符串】 Z-algorithm
    【字符串】KMP
    【神奇性质】【P5523】D [yLOI2019] 珍珠
    【线段树】【P5522】[yLOI2019] 棠梨煎雪
  • 原文地址:https://www.cnblogs.com/abclzr/p/5336419.html
Copyright © 2011-2022 走看看