Cod sursa(job #3157300)

Utilizator cezar_titianuTitianu Cezar cezar_titianu Data 15 octombrie 2023 12:05:56
Problema Hotel Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.15 kb
#include <cmath>
#include <fstream>
#include <vector>

class aint {
private:
	struct aint_node {
		int pref = 0;
		int sol = 0;
		int suf = 0;

		int lazy = 1; // 0 - update 0, 1 - update 1, -1 - clear
	};
	int size;
	std::vector <aint_node> vec;

	void propag (int nod, int st, int mid, int dr) {
		if (vec[nod].lazy != -1 && 2 * nod + 2 < vec.size()) {
			int len_st = mid - st + 1;
			int len_dr = dr - mid;
			if (vec[nod].lazy == 1) {
				len_st = len_dr = 0;
			}

			vec[2 * nod + 1].pref = len_st;
			vec[2 * nod + 1].sol = len_st;
			vec[2 * nod + 1].suf = len_st;
			vec[2 * nod + 1].lazy = vec[nod].lazy;
			vec[2 * nod + 2].pref = len_dr;
			vec[2 * nod + 2].sol = len_dr;
			vec[2 * nod + 2].suf = len_dr;
			vec[2 * nod + 2].lazy = vec[nod].lazy;
			vec[nod].lazy = -1;
		}
	}

	aint_node merge (const aint_node &nod_st, const aint_node &nod_dr, int st, int mid, int dr) {
		aint_node par;
		int len_st = mid - st + 1;
		int len_dr = dr - mid;

		par.pref = (nod_st.pref == len_st ? nod_st.pref + nod_dr.pref : nod_st.pref);
		par.suf = (nod_dr.suf == len_dr ? nod_dr.suf + nod_st.suf : nod_dr.suf);
		par.sol = std::max(std::max(nod_st.sol, nod_dr.sol), nod_st.suf + nod_dr.pref);

		par.lazy = -1;
		return par;
	}

	void update_priv (int nod, int st, int dr, int pos1, int pos2, bool state) {
		if (st == pos1 && dr == pos2) {
			int len = (state ? 0 : st - dr + 1);
			vec[nod].pref = len;
			vec[nod].sol = len;
			vec[nod].suf = len;
			vec[nod].lazy = (state ? 1 : 0);
		}
		else {
			int mid = (st + dr) / 2;
			propag(nod, st, mid, dr);
			if (pos1 <= mid) {
				update_priv(2 * nod + 1, st, mid, pos1, std::min(pos2, mid), state);
			}
			if (mid < pos2) {
				update_priv(2 * nod + 2, mid + 1, dr, std::max(pos1, mid + 1), pos2, state);
			}
			vec[nod] = merge(vec[2 * nod + 1], vec[2 * nod + 2], st, mid, dr);
		}
	}

	aint_node query_priv (int nod, int st, int dr, int pos1, int pos2) {
		if (st == pos1 && dr == pos2) {
			return vec[nod];
		}
		else {
			int mid = (st + dr) / 2;
			propag(nod, st, mid, dr);
			aint_node sol_st, sol_dr;
			if (pos1 <= mid) {
				sol_st = query_priv(2 * nod + 1, st, mid, pos1, std::min(pos2, mid));
			}
			if (mid < pos2) {
				sol_dr = query_priv(2 * nod + 2, mid + 1, dr, std::max(pos1, mid + 1), pos2);
			}
			return merge(sol_st, sol_dr, st, mid, dr);
		}
	}

public:
	void reset (bool state) {
		int len = (state ? 0 : size);
		vec[0].pref = len;
		vec[0].sol = len;
		vec[0].suf = len;
		vec[0].lazy = (state ? 1 : 0);
	}

	aint (int set_size) {
		size = set_size;
		vec.resize(4 * size);
		reset(0);
	}

	int query () {
		return query_priv(0, 0, size - 1, 0, size - 1).sol;
	}

	void update (int pos1, int pos2, bool state) {
		update_priv(0, 0, size - 1, pos1, pos2, state);
	}
};

int main () {
	std::ifstream fin("hotel.in");
	std::ofstream fout("hotel.out");

	int n, p;
	fin >> n >> p;
	aint solve(n);

	int cer, pos, len;
	for (int i = 0; i < p; i++) {
		fin >> cer;
		if (cer == 3) {
			fout << solve.query() << '\n';
		}
		else {
			fin >> pos >> len;
			pos--;
			solve.update(pos, pos + len - 1, cer == 1);
		}
	}
}
/*
12 10
000000000000
3
1 2 3
011100000000
1 9 4
011100001111
3
2 2 1
001100001111
3
2 9 2
001100000011
3
2 3 2
000000000011
3
*/