cp_library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub SSRS-cp/cp_library

:warning: old_Data_Structures/Segment_Tree_Beats.cpp

Code

template <typename T>
struct segment_tree_beats{
	int N;
	vector<T> max1, max2, min1, min2;
	vector<T> add, sum;
	vector<int> maxc, minc, len;
	void update_max(int i, T x){
		sum[i] += (x - max1[i]) * maxc[i];
		if (max1[i] == min1[i]){
			min1[i] = x;
		} else if (max1[i] == min2[i]){
			min2[i] = x;
		}
		max1[i] = x;
	}
	void update_min(int i, T x){
		sum[i] += (x - min1[i]) * minc[i];
		if (min1[i] == max1[i]){
			max1[i] = x;
		} else if (min1[i] == max2[i]){
			max2[i] = x;
		}
		min1[i] = x;
	}
	void update_add(int i, T x){
		max1[i] += x;
		if (max2[i] != -INF){
			max2[i] += x;
		}
		min1[i] += x;
		if (min2[i] != INF){
			min2[i] += x;
		}
		sum[i] += x * len[i];
		add[i] += x;
	}
	void push(int i){
		if (i >= N - 1){
			return;
		}
		int l = i * 2 + 1;
		int r = i * 2 + 2;
		if (add[i] != 0){
			update_add(l, add[i]);
			update_add(r, add[i]);
			add[i] = 0;
		}
		if (max1[i] < max1[l]){
			update_max(l, max1[i]);
		}
		if (min1[i] > min1[l]){
			update_min(l, min1[i]);
		}
		if (max1[i] < max1[r]){
			update_max(r, max1[i]);
		}
		if (min1[i] > min1[r]){
			update_min(r, min1[i]);
		}
	}
	void update(int i){
		int l = i * 2 + 1;
		int r = i * 2 + 2;
		sum[i] = sum[l] + sum[r];
		if (max1[l] > max1[r]){
			max1[i] = max1[l];
			max2[i] = max(max2[l], max1[r]);
			maxc[i] = maxc[l];
		} else if (max1[l] < max1[r]){
			max1[i] = max1[r];
			max2[i] = max(max1[l], max2[r]);
			maxc[i] = maxc[r];
		} else {
			max1[i] = max1[l];
			max2[i] = max(max2[l], max2[r]);
			maxc[i] = maxc[l] + maxc[r];
		}
		if (min1[l] < min1[r]){
			min1[i] = min1[l];
			min2[i] = min(min2[l], min1[r]);
			minc[i] = minc[l];
		} else if (min1[l] > min1[r]){
			min1[i] = min1[r];
			min2[i] = min(min1[l], min2[r]);
			minc[i] = minc[r];
		} else {
			min1[i] = min1[l];
			min2[i] = min(min2[l], min2[r]);
			minc[i] = minc[l] + minc[r];
		}
	}
	segment_tree_beats(vector<T> A){
		int n = A.size();
		N = 1;
		while (N < n){
			N *= 2;
		}
		max1 = vector<T>(N * 2 - 1, -INF);
		max2 = vector<T>(N * 2 - 1, -INF);
		min1 = vector<T>(N * 2 - 1, INF);
		min2 = vector<T>(N * 2 - 1, INF);
		add = vector<T>(N * 2 - 1, 0);
		sum = vector<T>(N * 2 - 1, 0);
		maxc = vector<int>(N * 2 - 1, 0);
		minc = vector<int>(N * 2 - 1, 0);
		len = vector<int>(N * 2 - 1, 1);
		for (int i = 0; i < n; i++){
			max1[N - 1 + i] = A[i];
			min1[N - 1 + i] = A[i];
			sum[N - 1 + i] = A[i];
			maxc[N - 1 + i] = 1;
			minc[N - 1 + i] = 1;
		}
		for (int i = N - 2; i >= 0; i--){
			len[i] = len[i * 2 + 1] + len[i * 2 + 2];
			update(i);
		}
	}
	void range_chmin(int L, int R, T x, int i, int l, int r){
		if (r <= L || R <= l || x >= max1[i]){
			return;
		} else if (L <= l && r <= R && x > max2[i]){
			update_max(i, x);
			return;
		}
		push(i);
		int m = (l + r) / 2;
		range_chmin(L, R, x, i * 2 + 1, l, m);
		range_chmin(L, R, x, i * 2 + 2, m, r);
		update(i);
	}
	void range_chmin(int L, int R, T x){
		range_chmin(L, R, x, 0, 0, N);
	}
	void range_chmax(int L, int R, T x, int i, int l, int r){
		if (r <= L || R <= l || x <= min1[i]){
			return;
		} else if (L <= l && r <= R && x < min2[i]){
			update_min(i, x);
			return;
		}
		push(i);
		int m = (l + r) / 2;
		range_chmax(L, R, x, i * 2 + 1, l, m);
		range_chmax(L, R, x, i * 2 + 2, m, r);
		update(i);
	}
	void range_chmax(int L, int R, T x){
		range_chmax(L, R, x, 0, 0, N);
	}
	void range_add(int L, int R, T x, int i, int l, int r){
		if (r <= L || R <= l){	
			return;
		} else if (L <= l && r <= R){
			update_add(i, x);
			return;
		}
		push(i);
		int m = (l + r) / 2;
		range_add(L, R, x, i * 2 + 1, l, m);
		range_add(L, R, x, i * 2 + 2, m, r);
		update(i);
	}
	void range_add(int L, int R, T x){
		range_add(L, R, x, 0, 0, N);
	}
	T range_sum(int L, int R, int i, int l, int r){
		if (r <= L || R <= l){
			return 0;
		} else if (L <= l && r <= R){
			return sum[i];
		}
		push(i);
		int m = (l + r) / 2;
		return range_sum(L, R, i * 2 + 1, l, m) + range_sum(L, R, i * 2 + 2, m, r);
	}
	T range_sum(int L, int R){
		return range_sum(L, R, 0, 0, N);
	}
};
#line 1 "old_Data_Structures/Segment_Tree_Beats.cpp"
template <typename T>
struct segment_tree_beats{
	int N;
	vector<T> max1, max2, min1, min2;
	vector<T> add, sum;
	vector<int> maxc, minc, len;
	void update_max(int i, T x){
		sum[i] += (x - max1[i]) * maxc[i];
		if (max1[i] == min1[i]){
			min1[i] = x;
		} else if (max1[i] == min2[i]){
			min2[i] = x;
		}
		max1[i] = x;
	}
	void update_min(int i, T x){
		sum[i] += (x - min1[i]) * minc[i];
		if (min1[i] == max1[i]){
			max1[i] = x;
		} else if (min1[i] == max2[i]){
			max2[i] = x;
		}
		min1[i] = x;
	}
	void update_add(int i, T x){
		max1[i] += x;
		if (max2[i] != -INF){
			max2[i] += x;
		}
		min1[i] += x;
		if (min2[i] != INF){
			min2[i] += x;
		}
		sum[i] += x * len[i];
		add[i] += x;
	}
	void push(int i){
		if (i >= N - 1){
			return;
		}
		int l = i * 2 + 1;
		int r = i * 2 + 2;
		if (add[i] != 0){
			update_add(l, add[i]);
			update_add(r, add[i]);
			add[i] = 0;
		}
		if (max1[i] < max1[l]){
			update_max(l, max1[i]);
		}
		if (min1[i] > min1[l]){
			update_min(l, min1[i]);
		}
		if (max1[i] < max1[r]){
			update_max(r, max1[i]);
		}
		if (min1[i] > min1[r]){
			update_min(r, min1[i]);
		}
	}
	void update(int i){
		int l = i * 2 + 1;
		int r = i * 2 + 2;
		sum[i] = sum[l] + sum[r];
		if (max1[l] > max1[r]){
			max1[i] = max1[l];
			max2[i] = max(max2[l], max1[r]);
			maxc[i] = maxc[l];
		} else if (max1[l] < max1[r]){
			max1[i] = max1[r];
			max2[i] = max(max1[l], max2[r]);
			maxc[i] = maxc[r];
		} else {
			max1[i] = max1[l];
			max2[i] = max(max2[l], max2[r]);
			maxc[i] = maxc[l] + maxc[r];
		}
		if (min1[l] < min1[r]){
			min1[i] = min1[l];
			min2[i] = min(min2[l], min1[r]);
			minc[i] = minc[l];
		} else if (min1[l] > min1[r]){
			min1[i] = min1[r];
			min2[i] = min(min1[l], min2[r]);
			minc[i] = minc[r];
		} else {
			min1[i] = min1[l];
			min2[i] = min(min2[l], min2[r]);
			minc[i] = minc[l] + minc[r];
		}
	}
	segment_tree_beats(vector<T> A){
		int n = A.size();
		N = 1;
		while (N < n){
			N *= 2;
		}
		max1 = vector<T>(N * 2 - 1, -INF);
		max2 = vector<T>(N * 2 - 1, -INF);
		min1 = vector<T>(N * 2 - 1, INF);
		min2 = vector<T>(N * 2 - 1, INF);
		add = vector<T>(N * 2 - 1, 0);
		sum = vector<T>(N * 2 - 1, 0);
		maxc = vector<int>(N * 2 - 1, 0);
		minc = vector<int>(N * 2 - 1, 0);
		len = vector<int>(N * 2 - 1, 1);
		for (int i = 0; i < n; i++){
			max1[N - 1 + i] = A[i];
			min1[N - 1 + i] = A[i];
			sum[N - 1 + i] = A[i];
			maxc[N - 1 + i] = 1;
			minc[N - 1 + i] = 1;
		}
		for (int i = N - 2; i >= 0; i--){
			len[i] = len[i * 2 + 1] + len[i * 2 + 2];
			update(i);
		}
	}
	void range_chmin(int L, int R, T x, int i, int l, int r){
		if (r <= L || R <= l || x >= max1[i]){
			return;
		} else if (L <= l && r <= R && x > max2[i]){
			update_max(i, x);
			return;
		}
		push(i);
		int m = (l + r) / 2;
		range_chmin(L, R, x, i * 2 + 1, l, m);
		range_chmin(L, R, x, i * 2 + 2, m, r);
		update(i);
	}
	void range_chmin(int L, int R, T x){
		range_chmin(L, R, x, 0, 0, N);
	}
	void range_chmax(int L, int R, T x, int i, int l, int r){
		if (r <= L || R <= l || x <= min1[i]){
			return;
		} else if (L <= l && r <= R && x < min2[i]){
			update_min(i, x);
			return;
		}
		push(i);
		int m = (l + r) / 2;
		range_chmax(L, R, x, i * 2 + 1, l, m);
		range_chmax(L, R, x, i * 2 + 2, m, r);
		update(i);
	}
	void range_chmax(int L, int R, T x){
		range_chmax(L, R, x, 0, 0, N);
	}
	void range_add(int L, int R, T x, int i, int l, int r){
		if (r <= L || R <= l){	
			return;
		} else if (L <= l && r <= R){
			update_add(i, x);
			return;
		}
		push(i);
		int m = (l + r) / 2;
		range_add(L, R, x, i * 2 + 1, l, m);
		range_add(L, R, x, i * 2 + 2, m, r);
		update(i);
	}
	void range_add(int L, int R, T x){
		range_add(L, R, x, 0, 0, N);
	}
	T range_sum(int L, int R, int i, int l, int r){
		if (r <= L || R <= l){
			return 0;
		} else if (L <= l && r <= R){
			return sum[i];
		}
		push(i);
		int m = (l + r) / 2;
		return range_sum(L, R, i * 2 + 1, l, m) + range_sum(L, R, i * 2 + 2, m, r);
	}
	T range_sum(int L, int R){
		return range_sum(L, R, 0, 0, N);
	}
};
Back to top page