Submission #1274686

#TimeUsernameProblemLanguageResultExecution timeMemory
1274686crispxxWall (IOI14_wall)C++20
100 / 100
828 ms243152 KiB
#include "wall.h"

#include <bits/stdc++.h>
using namespace std;

// #define int long long
#define all(x) x.begin(), x.end()
#define pb push_back
#define ar array
#define nl '\n'

template <typename A, typename B>
bool chmin(A &a, const B &b) {
	if(a > b) {
		return a = b, true;
	}
	return false;
}

template <typename A, typename B>
bool chmax(A &a, const B &b) {
	if(a < b) {
		return a = b, true;
	}
	return false;
}

const int inf = 1e9;

struct node {
	int val, mn, mn2, mx, mx2, cnmn, cnmx;
	
	node() : val(0), mn(inf), mn2(inf), mx(-inf), mx2(-inf), cnmn(0), cnmx(0) {}
	
	node(int x) : val(x), mn(x), mn2(inf), mx(x), mx2(-inf), cnmn(1), cnmx(1) {}
	
	void merge(node &l, node &r) {
		val = l.val + r.val;
		
		mn = min(l.mn, r.mn);
		mx = max(l.mx, r.mx);
		
		cnmn = (l.mn == mn) * l.cnmn + (r.mn == mn) * r.cnmn;
		cnmx = (l.mx == mx) * l.cnmx + (r.mx == mx) * r.cnmx;
		
		if(mn == l.mn) {
			if(mn == r.mn) mn2 = min(l.mn2, r.mn2);
			else mn2 = min(l.mn2, r.mn);
		} else {
			mn2 = min(l.mn, r.mn2);
		}
		
		if(mx == l.mx) {
			if(mx == r.mx) mx2 = max(l.mx2, r.mx2);
			else mx2 = max(l.mx2, r.mx);
		} else {
			mx2 = max(l.mx, r.mx2);
		}	
	}
};

struct segtree {
	int n; vector<node> t;
	
	segtree(vector<int> a) : n(a.size()), t(n << 2) {
		build(1, 1, n, a);
	}
	
	void build(int v, int l, int r, vector<int> &a) {
		if(l == r) {
			t[v] = node(a[l - 1]);
			return;
		}
		
		int m = (l + r) >> 1;
		
		build(v << 1, l, m, a);
		build(v << 1 | 1, m + 1, r, a);
		
		t[v].merge(t[v << 1], t[v << 1 | 1]);
	}
	
	void push_min(int v, int x, bool f) {
		if(x <= t[v].mn) return;
		t[v].val += t[v].cnmn * (x - t[v].mn);
		t[v].mn = x;
		if(f) {
			t[v].mx = x;
		} else {
			if(x >= t[v].mx) {
				t[v].mx = x;
			} else if(x > t[v].mx2) {
				t[v].mx2 = x;
			}
		}
	}
	
	void push_max(int v, int x, bool f) {
		if(x >= t[v].mx) return;
		t[v].val -= t[v].cnmx * (t[v].mx - x);
		t[v].mx = x;
		if(f) {
			t[v].mn = x;
		} else {
			if(x <= t[v].mn) {
				t[v].mn = x;
			} else if(x < t[v].mn2) {
				t[v].mn2 = x;
			}
		}
	}
	
	void push(int v, int l, int r) {
		int m = (l + r) >> 1;
		
		push_min(v << 1, t[v].mn, l == m);
		push_min(v << 1 | 1, t[v].mn, m + 1 == r);
		
		push_max(v << 1, t[v].mx, l == m);
		push_max(v << 1 | 1, t[v].mx, m + 1 == r);
	}
	
	void setmin(int v, int l, int r, int ll, int rr, int x) {
		if(l > rr || ll > r || t[v].mx <= x) return;
		
		if(l >= ll && r <= rr && t[v].mx2 < x) {
			push_max(v, x, l == r);
			return;
		}
		
		push(v, l, r);
		
		int m = (l + r) >> 1;
		
		setmin(v << 1, l, m, ll, rr, x);
		setmin(v << 1 | 1, m + 1, r, ll, rr, x);
		
		t[v].merge(t[v << 1], t[v << 1 | 1]);
	}
	
	void setmin(int l, int r, int x) {
		setmin(1, 1, n, l, r, x);
	}
	
	void setmax(int v, int l, int r, int ll, int rr, int x) {
		if(l > rr || ll > r || t[v].mn >= x) return;
		
		if(l >= ll && r <= rr && t[v].mn2 > x) {
			push_min(v, x, l == r);
			return;
		}
		
		push(v, l, r);
		
		int m = (l + r) >> 1;
		
		setmax(v << 1, l, m, ll, rr, x);
		setmax(v << 1 | 1, m + 1, r, ll, rr, x);
		
		t[v].merge(t[v << 1], t[v << 1 | 1]);
	}
	
	void setmax(int l, int r, int x) {
		setmax(1, 1, n, l, r, x);
	}
	
	int get(int v, int l, int r, int i) {
		if(l == r) return t[v].val;
		
		push(v, l, r);
		
		int m = (l + r) >> 1;
		
		if(i <= m) return get(v << 1, l, m, i);
		return get(v << 1 | 1, m + 1, r, i);
	}
	
	int get(int i) {
		return get(1, 1, n, i);
	}
};

void buildWall(int n, int k, int op[], int left[], int right[], int height[], int finalHeight[]){
	vector<int> a(n);
	
	segtree t(a);
	
	for(int i = 0; i < k; i++) {
		// cout << "Query ";
		
		if(op[i] == 1) {
			// cout << "setmax: " << left[i] + 1 << ' ' << right[i] + 1 << ' ' << height[i] << endl;
			t.setmax(left[i] + 1, right[i] + 1, height[i]);
		} else {
			// cout << "setmin: " << left[i] + 1 << ' ' << right[i] + 1 << ' ' << height[i] << endl;
			t.setmin(left[i] + 1, right[i] + 1, height[i]);
		}
		
		// for(int j = 0; j < n; j++) {
			// cout << t.get(j + 1) << ' ';
		// }
		
		// cout << nl;
		
	}
	
	for(int i = 0; i < n; i++) {
		finalHeight[i] = t.get(i + 1);
	}
}

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...