ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P2894 [USACO08FEB]Hotel G

2021-10-07 11:02:55  阅读:188  来源: 互联网

标签:lc int sum Hotel rmax mid USACO08FEB rc P2894


题意就是维护整个序列最长连续01的位置,要求位置最左边,就是线段树最大连续子段和的查询操作稍作修改,每次查询分类讨论,如果左儿子内已经有满足题意的长度,就往左儿子找,如果左右凑起来有的话,就从左右凑起来,再查询右儿子有没有满足题意的长度.

#include<iostream>
#include<cstdio>
#define rep(i,j,k) for(register int i(j);i<=k;++i)
#define drp(i,j,k) for(register int i(j);i>=k;--i)
#define bug cout<<"~~~~~~~~~~~~~"<<'\n';
#define bugout(x) cout<<x<<endl;
using std::cin;
using std::cout;
typedef long long lxl;
template<typename T>
inline T  max(T a, T b) {
	return a > b ? a : b;
}
template<typename T>
inline T  min(T a, T b) {
	return a < b ? a : b;
}

inline char gt() {
	static char buf[1 << 21], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
template <typename T>
inline void  read(T &x) {
	register char ch = gt();
	x = 0;
	int w(0);
	while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt();
	while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt();
	w ? x = ~(x - 1) : x;
}
template <typename T>
inline void out(T x, char cc) {
	if(x < 0) x = -x, putchar('-');
	char ch[20];
	int num(0);
	while(x || !num) ch[++num] = x % 10 + '0', x /= 10;
	while(num) putchar(ch[num--]);
	putchar(cc);
}

const int N = 5e4 + 79;
struct SegmentTree {

	int sum[N << 2], lmax[N << 2], rmax[N << 2];
	int lc[N << 2], rc[N << 2], tag[N << 2];
	int rt, cnt;

	inline void pushdown(int p, int L, int R) {
		if(tag[p] == -1) return ;

		int mid((L + R >> 1));
		if(tag[p] == 1) {

			sum[lc[p]] = lmax[lc[p]] = rmax[lc[p]] = mid - L + 1;
			sum[rc[p]] = lmax[rc[p]] = rmax[rc[p]] = R - mid;
		} else {
			sum[lc[p]] = lmax[lc[p]] = rmax[lc[p]] = 0;
			sum[rc[p]] = lmax[rc[p]] = rmax[rc[p]] = 0;
		}

		tag[lc[p]] = tag[rc[p]] = tag[p];
		tag[p] = -1;
	}

	inline void pushup(int p, int L, int R) {

		int mid(L + R >> 1);

		if(sum[lc[p]] == mid - L + 1) {
			lmax[p] = (mid - L + 1) + lmax[rc[p]];
		} else {
			lmax[p] = lmax[lc[p]];
		}

		if(sum[rc[p]] == R - mid) {
			rmax[p] = (R - mid) + rmax[lc[p]];
		} else {
			rmax[p] = rmax[rc[p]];
		}
		sum[p] = max(max(sum[lc[p]], sum[rc[p]]), rmax[lc[p]] + lmax[rc[p]]);

	}
	inline void build(int &p, int L, int R) {
		if(!p) p = ++cnt;
		tag[p] = -1;
		sum[p] = lmax[p] = rmax[p] = R - L + 1;
		if(L == R) {
			return ;
		}
		int mid(L + R >> 1);
		build(lc[p], L, mid);
		build(rc[p], mid + 1, R);
	}
	inline void change(int p, int L, int R, int ll, int rr, int val) {
		if(ll <= L && rr >= R) {
			if(val == 1) {
				sum[p] = lmax[p] = rmax[p] = R - L + 1;
				tag[p] = val;
			} else {
				sum[p] = lmax[p] = rmax[p] = 0;
				tag[p] = val;
			}
			return;
		}
		pushdown(p, L, R);
		int mid(L + R >> 1);
		if(ll <= mid) change(lc[p], L, mid, ll, rr, val);
		if(rr > mid) change(rc[p], mid + 1, R, ll, rr, val);
		pushup(p, L, R);
	}

	inline int query(int p, int L, int R, int len) {
		if(L == R) return L;
		pushdown(p, L, R);
		int mid(L + R >> 1);
		if(sum[lc[p]] >= len) return query(lc[p], L, mid, len);
		else if(rmax[lc[p]] + lmax[rc[p]] >= len) return mid - rmax[lc[p]] + 1; //左边的不够,加上右边够了
		else if(sum[rc[p]] >= len) return query(rc[p], mid + 1, R, len);
		return 0;
	}
} S; //空闲的当1,求区间最长连续子段和

int n, m, k;

int main() {
//	freopen("hotel.in", "r", stdin);
//	freopen("hotel.out", "w", stdout);
	read(n);
	read(m);

	S.build(S.rt, 1, n);

	int x, p;
	while(m--) {
		read(k);
		if(k == 1) {
			read(p);
			if(S.sum[S.rt] < p) {
				out(0, '\n');
			} else {
				int po = S.query(S.rt, 1, n, p);
				out(po, '\n');
				S.change(S.rt, 1, n, po, po + p - 1, 0);
			}
		} else {
			read(x);
			read(p);
			S.change(S.rt, 1, n, x, x + p - 1, 1);
		}
	}
	return 0;
}

标签:lc,int,sum,Hotel,rmax,mid,USACO08FEB,rc,P2894
来源: https://www.cnblogs.com/QQ2519/p/15375298.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有