結果

問題 No.230 Splarraay スプラレェーイ
ユーザー kurenai3110kurenai3110
提出日時 2016-09-02 05:22:22
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 147 ms / 5,000 ms
コード長 3,411 bytes
コンパイル時間 763 ms
コンパイル使用メモリ 78,864 KB
実行使用メモリ 9,444 KB
最終ジャッジ日時 2023-08-09 20:23:52
合計ジャッジ時間 2,727 ms
ジャッジサーバーID
(参考情報)
judge13 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,376 KB
testcase_01 AC 1 ms
4,376 KB
testcase_02 AC 2 ms
4,384 KB
testcase_03 AC 1 ms
4,384 KB
testcase_04 AC 2 ms
4,384 KB
testcase_05 AC 2 ms
4,380 KB
testcase_06 AC 9 ms
4,376 KB
testcase_07 AC 2 ms
4,380 KB
testcase_08 AC 3 ms
4,376 KB
testcase_09 AC 66 ms
6,224 KB
testcase_10 AC 73 ms
4,376 KB
testcase_11 AC 40 ms
4,644 KB
testcase_12 AC 71 ms
6,320 KB
testcase_13 AC 12 ms
4,384 KB
testcase_14 AC 69 ms
9,404 KB
testcase_15 AC 103 ms
9,444 KB
testcase_16 AC 123 ms
9,352 KB
testcase_17 AC 147 ms
9,376 KB
testcase_18 AC 96 ms
9,396 KB
testcase_19 AC 88 ms
9,404 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;

#define rep(i,n) for(int i=0;i<n;i++)
#define repr(i,n) for(int i=n-1;i>=0;i--)

struct ST {
	//seg木と遅延
	vector<ll> lazy;
	vector<pair<ll, ll> >seg;

	int size;

	ST(int n) {
		//seg木のサイズは(nが入るような2のべき乗のサイズ)*2
		size = 1;
		while (size < n) size *= 2;
		seg.resize(size * 2);
		lazy.resize(size * 2, -1);  //-1で初期化
	}

	//遅延評価
	void push(int k, int l, int r) {
		if (lazy[k] != -1) {    //遅延があるなら
			//ノードkは区間内の1(first)と2(second)の数
			//ノードkを更新
			if (lazy[k] % 2) {
				seg[k] = make_pair(r - l, 0);
			}
			else {
				seg[k] = make_pair(0, r - l);
			}
			if (r - l > 1) {    //子ノードがあるなら
				lazy[k * 2 + 1] = lazy[k];  //ノードkの子(左)に伝搬
				lazy[k * 2 + 2] = lazy[k];  //ノードkの子(右)に伝搬
			}
			lazy[k] = -1;                   //ノードkは伝搬し終わった
		}
	}

	ll merge(ll x, ll y) {
		return x + y;
	}

	//[a,b)をvに
	//[l,r)はノードが持つ区間
	void update(int a, int b, ll v, int k, int l, int r) {
		//ノードkに対して遅延があるかもしれない
		//その時ノードkは更新される
		push(k, l, r);

		if (r <= a || b <= l) return;   //[a,b)がノードkの区間[l,r)と交差しない
		if (a <= l && r <= b) {         //[a,b)がノードkを完全に含む
			lazy[k] = v;    //ノードkの区間[l,r)はすべてvになったという情報
			push(k, l, r);  //子に伝搬
							//ノードkを更新
		}
		else {							//その他
			//左の子をupdate
			update(a, b, v, k * 2 + 1, l, (l + r) / 2);
			//右の子をupdate
			update(a, b, v, k * 2 + 2, (l + r) / 2, r);
			//ノードkを更新
			seg[k] = make_pair(merge(seg[k * 2 + 1].first, seg[k * 2 + 2].first), merge(seg[k * 2 + 1].second, seg[k * 2 + 2].second));
		}
	}

	void update(int a, int b, ll v) {
		update(a, b, v, 0, 0, size);
	}

	//[a,b)の1,2の数
	//[l,r)はノードが持つ区間
	pair<ll,ll> query(int a, int b, int k, int l, int r) {
		//ノードkに対して遅延があるかもしれない
		//その時ノードkは更新される
		push(k, l, r);

		if (r <= a || b <= l) return make_pair(0, 0);             //[a,b)がノードkの区間[l,r)と交差しない時0を返す
		if (a <= l && r <= b) return seg[k];        //[a,b)がノードkを完全に含む時そのノードの値を返す
		//左の子の1,2の数
		pair<ll, ll> x = query(a, b, k * 2 + 1, l, (l + r) / 2);
		//右の子の1,2の数
		pair<ll, ll> y = query(a, b, k * 2 + 2, (l + r) / 2, r);

		return make_pair(merge(x.first,y.first), merge(x.second,y.second));//子の1,2のそれぞれの和を返す
	}

	pair<ll, ll> query(int a, int b) {
		return query(a, b, 0, 0, size);
	}
};

int main() {
	ll n,a=0,b=0;
	cin >> n;
	ST st(n);

	int q; cin >> q;
	for (int i = 0; i < q; i++) {
		int x; cin >> x;
		int l, r;
		cin >> l >> r;
		r++;
		if (x == 1) {
			st.update(l, r, x);
		}else if(x==2){
			st.update(l, r, x);
		}
		else if (x == 0) {
			pair<ll, ll> bonus;
			bonus = st.query(l, r);

			if (bonus.first > bonus.second) a += bonus.first;
			else if (bonus.first < bonus.second) b += bonus.second;
		}
	}
	pair<ll, ll>result;
	result = st.query(0, n);

	cout << a + result.first << " " << b + result.second << endl;

	return 0;
}
0