Submission #701709

#TimeUsernameProblemLanguageResultExecution timeMemory
701709GusterGoose27Safety (NOI18_safety)C++11
100 / 100
401 ms36560 KiB
#include <bits/stdc++.h>

using namespace std;

#define int long long

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 2e5;
const int inf = 2e9;
int n, h;
int heights[MAXN];
mt19937 gen(0);

pii operator+(pii a, pii b) {
	return pii(a.first+b.first, a.second+b.second);
}

class Node;

class Node {
public:
	Node *l = nullptr;
	Node *r = nullptr;
	unsigned int key;
	pii val; //
	pii sum;
	Node(pii v) : val(v) {
		key = gen();
		sum = val;
	}
	static pii get_val(Node *rt) {
		return (rt == nullptr) ? pii(0, 0) : rt->val;
	}
	static pii get_sum(Node *rt) {
		return (rt == nullptr) ? pii(0, 0) : rt->sum;
	}
	void make_sum() {
		sum = val+get_sum(l)+get_sum(r);
	}
	void make_inorder(vector<pii> &res) {
		if (l) l->make_inorder(res);
		res.push_back(val);
		if (r) r->make_inorder(res);
	}
};

void merge(Node *l, Node *r, Node *&rt) {
	if (l == nullptr) {
		rt = r;
		return;
	}
	if (r == nullptr) {
		rt = l;
		return;
	}
	if (l->key < r->key) {
		rt = l;
		merge(l->r, r, l->r);
		return rt->make_sum();
	}
	rt = r;
	merge(l, r->l, r->l);
	rt->make_sum();
}

void split(Node *rt, Node *&l, Node *&r, int v) { // split by x-value, for adding a new line
	int amt = Node::get_sum(rt->l).second;
	if (amt > v) {
		r = rt;
		split(rt->l, l, r->l, v);
		return r->make_sum();
	}
	if (amt+rt->val.second < v) {
		l = rt;
		split(rt->r, l->r, r, v-amt-rt->val.second);
		return l->make_sum();
	}
	r = rt->r;
	l = rt;
	l->r = nullptr;
	return l->make_sum();
}

void split2(Node *rt, Node *&l, Node *&r, int v) { // split by slope, for expanding
	int amt = Node::get_sum(rt->l).first;
	if (amt > v) {
		r = rt;
		split2(rt->l, l, r->l, v);
		return r->make_sum();
	}
	if (amt+rt->val.first < v) {
		l = rt;
		split2(rt->r, l->r, r, v-amt-rt->val.first);
		return l->make_sum();
	}
	l = rt->l;
	r = rt;
	r->l = nullptr;
	return r->make_sum();
}

int get_r_dist(Node *rt) {
	if (rt->r != nullptr) return get_r_dist(rt->r);
	return rt->val.second;
}

void set_r_dist(Node *rt, int v) {
	if (rt->r != nullptr) set_r_dist(rt->r, v);
	else rt->val.second = v;
	rt->make_sum();
}

void sub_l_slope(Node *rt, int v) {
	if (rt->l != nullptr) sub_l_slope(rt->l, v);
	else rt->val.first -= v;
	rt->make_sum();
}

signed main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	cin >> n >> h;
	for (int i = 0; i < n; i++) cin >> heights[i];
	Node *tree = new Node(pii(0, inf));
	int lzx = 0; // + amount by which tree is supposed to be left shifted
	int init_slope = 0; // + initial slope
	int y = 0;
	for (int i = n-1; i >= 0; i--) {
		Node *l;
		Node *r;
		split(tree, l, r, heights[i]+lzx);
		y += heights[i]+lzx;
		int rdist = Node::get_sum(l).second-heights[i]-lzx;
		int ldist = get_r_dist(l)-rdist;
		set_r_dist(l, ldist);
		Node *mid = new Node(pii(2, rdist));
		init_slope++;
		merge(l, mid, l);
		merge(l, r, tree);
		split2(tree, l, r, init_slope);
		int ex_slope = init_slope-Node::get_sum(l).first;
		sub_l_slope(r, ex_slope);
		mid = new Node(pii(ex_slope, 2*h));
		lzx += h;
		merge(l, mid, l);
		merge(l, r, tree);
	}
	Node *l;
	Node *r;
	split2(tree, l, r, init_slope);
	vector<pii> inorder;
	l->make_inorder(inorder);
	for (pii p: inorder) {
		init_slope -= p.first;
		y -= init_slope*p.second;
	}
	cout << y << "\n";
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...