Submission #1247264

#TimeUsernameProblemLanguageResultExecution timeMemory
1247264SpyrosAlivHorses (IOI15_horses)C++20
37 / 100
387 ms95396 KiB
#include "horses.h"
#include <bits/stdc++.h>
using namespace std;
#define ll long long

const ll MOD = 1e9+7;
const ll MAXV = 1e9;
const int MN = 5e5+5;
int n;
vector<int> x, y;
set<int> diff;

class SegTree {
	private:
	vector<ll> seg;
	ll query(int node, int start, int end, int l, int r) {
		if (start > r || end < l) return 1LL;
		else if (start >= l && end <= r) return seg[node];
		else {
			int mid = (start + end) / 2;
			return query(node*2+1, start, mid, l, r) * query(node*2+2, mid+1, end, l, r) % MOD;
		}
	}
	void update(int node, int start, int end, int idx, int v) {
		if (start == end) {
			seg[node] = v;
		}
		else {
			int mid = (start + end) / 2;
			if (idx <= mid) update(node*2+1, start, mid, idx, v);
			else update(node*2+2, mid+1, end, idx, v);
			seg[node] = seg[node*2+1] * seg[node*2+2] % MOD;
		}
	}
	public:
	void init(int nn) {
		seg.resize((nn + 1) * 8);
	}
	void upd(int idx, int v) {
		update(0, 0, n-1, idx, v);
	}
	ll query(int l, int r) {
		if (l > r) return 0;
		return query(0, 0, n-1, l, r);
	}
};

SegTree seg;

class SegTreeMax {
	private:
	struct Node {
		int maxv, idx;
	};
	vector<Node> seg;
	Node merge(Node a, Node b) {
		Node c = a;
		if (b.maxv > c.maxv) {
			c = b;
		}
		return c;
	}
	Node query(int node, int start, int end, int l, int r) {
		if (start > r || end < l) return {-1, -1};
		else if (start >= l && end <= r) return seg[node];
		else {
			int mid = (start + end) / 2;
			return merge(query(node*2+1, start, mid, l, r), query(node*2+2, mid+1, end, l, r));
		}
	}
	void update(int node, int start, int end, int idx, int v) {
		if (start == end) {
			seg[node] = {v, idx};
		}
		else {
			int mid = (start + end) / 2;
			if (idx <= mid) update(node*2+1, start, mid, idx, v);
			else update(node*2+2, mid+1, end, idx, v);
			seg[node] = merge(seg[node*2+1], seg[node*2+2]);
		}
	}
	public:
	void init(int nn) {
		seg.resize((nn + 1) * 8);
	}
	void upd(int idx, int v) {
		update(0, 0, n-1, idx, v);
	}
	int query(int l, int r) {
		if (l > r) return 0;
		return query(0, 0, n-1, l, r).idx;
	}
};

SegTreeMax maxSeg;

int get_ans() {
	vector<int> arr;
	for (int i = n-1; arr.size() < 32 && i >= 0; i--) {
		if (x[i] != 1) {
			arr.push_back(i);
			continue;
		}
		auto pp = diff.lower_bound(i);
		pp--;
		int prev = *pp + 1;
		arr.push_back(maxSeg.query(prev, i));
		i = prev;
	}
	reverse(arr.begin(), arr.end());
	int sz = arr.size();
	//for (int i = 0; i < sz; i++) {
	//	cout << arr[i] << " ";
	//}
	cout << "\n";
	ll dp = y[arr[sz-1]];
	int idx = arr[sz-1];
	for (int i = sz-2; i >= 0; i--) {
		ll dp2 = max((ll)y[arr[i]], (ll)x[arr[i + 1]] * dp);
		if (dp2 > MAXV) break;
		dp = dp2;
		idx = arr[i];
	}
	ll b4 = seg.query(0, idx);
	return (b4 * dp) % MOD;
}

int init(int N, int X[], int Y[]) {
	n = N;
	seg.init(n);
	maxSeg.init(n);
	diff.insert(-1);
	diff.insert(n+1);
	for (int i = 0; i < n; i++) {
		x.push_back(X[i]);
		y.push_back(Y[i]);
		seg.upd(i, X[i]);
		if (x[i] != 1) diff.insert(i);
		maxSeg.upd(i, y[i]);
	}
	return get_ans();
}

int updateX(int pos, int val) {	
	if (x[pos] != 1) diff.erase(pos);
	x[pos] = val;
	if (x[pos] != 1) diff.insert(pos);
	seg.upd(pos, x[pos]);
	return get_ans();
}

int updateY(int pos, int val) {
	y[pos] = val;
	maxSeg.upd(pos, val);
	return get_ans();
}
#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...